3eb781fcabCKRogwxJA3-jJKstw9Vg tools/control/xenctl.xml
3eb781fdl4lXWYZzmqDDUAYhAThRqQ tools/internal/Makefile
3eb781fdc539MQQm47rYRCCR3N5i-Q tools/internal/dom0_defs.h
-3ee609b3Yr4aggmLSKmhiIzT8-nURA tools/internal/dom0_ops.h
3eb781fdKiQbgozBsgs_zzJQ9ubehw tools/internal/mem_defs.h
3ec61e1bJCeJJu0SsptmDpA1xKvwvw tools/internal/rpm.spec
3eb781fdgbSkh2O6JQS-65Dz4n0ItQ tools/internal/xi_build.c
3eb781fdW1SAyiaC4mTsXq_9fRHh-A tools/internal/xi_create.c
3eb781fdcJ0fF7rWfzAOArW-x4-gwA tools/internal/xi_destroy.c
3ec43c5dmQxGDvgJJXbV1yLxT30Y1A tools/internal/xi_helper
-3eb83c3bZeECmphOKOJxSu4Lo1LpBw tools/internal/xi_list
+3f108ad5wQm0ZaQ4GXFoUhH1W1aW9w tools/internal/xi_list.c
3f0458aaXhD8BQAggO81gv30RQ-ifA tools/internal/xi_phys_grant.c
3f0458aaJHmlzkDwf0qxEzAcjX55sg tools/internal/xi_phys_probe.c
3f0458aaVAbFSwptQbQAnDOiZlwQ3w tools/internal/xi_phys_revoke.c
+3f108adb2b5OkKL6-faG3lMiOYDf_w tools/internal/xi_sched_domain.c
+3f108ade1v8weyh1sKx890VTd240Hw tools/internal/xi_sched_global.c
3eb781fd8oRfPgH7qTh7xvgmwD6NgA tools/internal/xi_start.c
3eb781fd0Eo9K1jEFCSAVzO51i_ngg tools/internal/xi_stop.c
+3f108ae2to5nHRRXfvUK7oxgjcW_yA tools/internal/xi_usage.c
3eb781fd7211MZsLxJSiuy7W4KnJXg tools/internal/xi_vifinit
3ddb79bcbOVHh38VJzc97-JEGD4dJQ xen/Makefile
3ddb79bcCa2VbsMp7mWKlhgwLQUQGA xen/README
3e5a4e65pP5spJErBW69pJxSSdK9RA xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_block.c
3e67f822FOPwqHiaRKbrskgWgoNL5g xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_block.h
3e677190SjkzJIvFifRVeYpIZOCtYA xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_ide.c
-3f045897EIYU5l5jxFBpeF1Z0ZOTwA xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_physdisk_proc.c
3e677193nOKKTLJzcAu4SYdbZaia8g xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_scsi.c
3e676eb5RXnHzSHgA1BvM0B1aIm4qg xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_segment.c
3e5d129aDldt6geU2-2SzBae34sQzg xenolinux-2.4.21-sparse/arch/xeno/drivers/block/xl_segment_proc.c
3e5a4e65G3e2s0ghPMgiJ-gBTUJ0uQ xenolinux-2.4.21-sparse/arch/xeno/drivers/console/Makefile
3e5a4e651TH-SXHoufurnWjgl5bfOA xenolinux-2.4.21-sparse/arch/xeno/drivers/console/console.c
3e5a4e656nfFISThfbyXQOA6HN6YHw xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/Makefile
-3e5a4e65Cc7io-vynYob10SlqXTjAQ xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_block.c
3e5a4e65BXtftInNHUC2PjDfPhdZZA xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_core.c
-3e5a4e65uXAx05p6B1-HU2tijuw8qA xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_memory.c
-3e5a4e65EOOLlPwXnhSuX-iVdWLmnA xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_ops.h
-3e6dba59C8o0kBks7UZ4IW_FY853Aw xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/sched_ops.c
3e5a4e65gfn_ltB8ujHMVFApnTTNRQ xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/vfr.c
3e5a4e65gZBRBB6RsSVg1c9iahigAw xenolinux-2.4.21-sparse/arch/xeno/drivers/network/Makefile
3e5a4e65ZxKrbFetVB84JhrTyZ1YuQ xenolinux-2.4.21-sparse/arch/xeno/drivers/network/network.c
3e5a4e6637ZDk0BvFEC-aFQs599-ng xenolinux-2.4.21-sparse/arch/xeno/lib/delay.c
3e5a4e66croVgpcJyJuF2ycQw0HuJw xenolinux-2.4.21-sparse/arch/xeno/mm/Makefile
3e5a4e66l8Q5Tv-6B3lQIRmaVbFPzg xenolinux-2.4.21-sparse/arch/xeno/mm/fault.c
-3e5a4e66TyNNUEXkr5RxqvQhXK1MQA xenolinux-2.4.21-sparse/arch/xeno/mm/get_unmapped_area.c
3e5a4e668SE9rixq4ahho9rNhLUUFQ xenolinux-2.4.21-sparse/arch/xeno/mm/hypervisor.c
3e5a4e661gLzzff25pJooKIIWe7IWg xenolinux-2.4.21-sparse/arch/xeno/mm/init.c
3f0bed43UUdQichXAiVNrjV-y2Kzcg xenolinux-2.4.21-sparse/arch/xeno/mm/ioremap.c
3e5a4e66qRlSTcjafidMB6ulECADvg xenolinux-2.4.21-sparse/arch/xeno/vmlinux.lds
3ea53c6em6uzVHSiGqrbbAVofyRY_g xenolinux-2.4.21-sparse/drivers/block/genhd.c
3e5a4e66mrtlmV75L1tjKDg8RaM5gA xenolinux-2.4.21-sparse/drivers/block/ll_rw_blk.c
+3f108aeaLcGDgQdFAANLTUEid0a05w xenolinux-2.4.21-sparse/drivers/char/mem.c
3e5a4e66rw65CxyolW9PKz4GG42RcA xenolinux-2.4.21-sparse/drivers/char/tty_io.c
3e5a4e669uzIE54VwucPYtGwXLAbzA xenolinux-2.4.21-sparse/fs/exec.c
3f05a939l8s0eQb_fpMvYiI06cTGlA xenolinux-2.4.21-sparse/fs/partitions/Config.in
3f05a939_I9vPADPgyVBwUDUxtoeOQ xenolinux-2.4.21-sparse/fs/partitions/xeno.h
3e5a4e66wbeCpsJgVf_U8Jde-CNcsA xenolinux-2.4.21-sparse/include/asm-xeno/bugs.h
3e5a4e66HdSkvIV6SJ1evG_xmTmXHA xenolinux-2.4.21-sparse/include/asm-xeno/desc.h
-3f0c3721E5WAnbeoPp7PE35J_Ndxaw xenolinux-2.4.21-sparse/include/asm-xeno/dom0.h
3e5a4e66SYp_UpAVcF8Lc1wa3Qtgzw xenolinux-2.4.21-sparse/include/asm-xeno/fixmap.h
3e5a4e67w_DWgjIJ17Tlossu1LGujQ xenolinux-2.4.21-sparse/include/asm-xeno/highmem.h
3e5a4e67YtcyDLQsShhCfQwPSELfvA xenolinux-2.4.21-sparse/include/asm-xeno/hw_irq.h
3e5a4e677VBavzM1UZIEcH1B-RlXMA xenolinux-2.4.21-sparse/include/asm-xeno/hypervisor.h
3e5a4e673p7PEOyHFm3nHkYX6HQYBg xenolinux-2.4.21-sparse/include/asm-xeno/irq.h
3ead095db_LRUXnxaqs0dA1DWhPoQQ xenolinux-2.4.21-sparse/include/asm-xeno/keyboard.h
-3e5a4e67zoNch27qYhEBpr2k6SABOg xenolinux-2.4.21-sparse/include/asm-xeno/mmu.h
3e5a4e678ddsQOpbSiRdy1GRcDc9WA xenolinux-2.4.21-sparse/include/asm-xeno/mmu_context.h
3e7270deQqtGPSnFxcW4AvJZuTUWfg xenolinux-2.4.21-sparse/include/asm-xeno/multicall.h
3e5a4e67mnQfh-R8KcQCaVo2Oho6yg xenolinux-2.4.21-sparse/include/asm-xeno/page.h
3e5a4e67uTYU5oEnIDjxuaez8njjqg xenolinux-2.4.21-sparse/include/asm-xeno/pgalloc.h
3e5a4e67X7JyupgdYkgDX19Huj2sAw xenolinux-2.4.21-sparse/include/asm-xeno/pgtable-2level.h
3e5a4e67gr4NLGtQ5CvSLimMYZlkOA xenolinux-2.4.21-sparse/include/asm-xeno/pgtable.h
+3f108af1qNv8DVSGPv4zpqIU1txCkg xenolinux-2.4.21-sparse/include/asm-xeno/proc_cmd.h
3e5a4e676uK4xErTBDH6XJREn9LSyg xenolinux-2.4.21-sparse/include/asm-xeno/processor.h
3e5a4e67AJPjW-zL7p-xWuA6IVeH1g xenolinux-2.4.21-sparse/include/asm-xeno/ptrace.h
3e5a4e68uJz-xI0IBVMD7xRLQKJDFg xenolinux-2.4.21-sparse/include/asm-xeno/segment.h
3eba8f878XjouY21EkQBXwYBsPsipQ xenolinux-2.4.21-sparse/lndir-rel
3e6e7c1efbQe93xCvOpOVCnXTMmQ5w xenolinux-2.4.21-sparse/mkbuildtree
3e5a4e68GxCIaFH4sy01v1wjapetaA xenolinux-2.4.21-sparse/mm/memory.c
+3f108af5VxPkLv13tXpXgoRKALQtXQ xenolinux-2.4.21-sparse/mm/mprotect.c
3e5a4e681xMPdF9xCMwpyfuYMySU5g xenolinux-2.4.21-sparse/mm/mremap.c
3e5a4e683HKVU-sxtagrDasRB8eBVw xenolinux-2.4.21-sparse/mm/swapfile.c
+3f108af81Thhb242EmKjGCYkjx-GJA xenolinux-2.4.21-sparse/mm/vmalloc.c
String command = vd.dumpForXen(vbd);
try {
- FileWriter fw = new FileWriter("/proc/xeno/dom0/vhd");
+ FileWriter fw = new FileWriter("/proc/xeno/vhd");
fw.write(command);
fw.flush();
fw.close();
} catch (IOException e) {
- throw new CommandFailedException("Could not write VBD details to /proc/xeno/dom0/vhd", e);
+ throw new CommandFailedException("Could not write VBD details to /proc/xeno/vhd", e);
}
return "Created virtual block device "
String command = vd.dumpForXen(vbd);
try {
- FileWriter fw = new FileWriter("/proc/xeno/dom0/vhd");
+ FileWriter fw = new FileWriter("/proc/xeno/vhd");
fw.write(command);
fw.flush();
fw.close();
} catch (IOException e) {
throw new CommandFailedException(
- "Could not write VBD details to /proc/xeno/dom0/vhd",
+ "Could not write VBD details to /proc/xeno/vhd",
e);
}
String line;
try {
- in = new BufferedReader(new FileReader("/proc/xeno/dom0/vhd"));
+ in = new BufferedReader(new FileReader("/proc/xeno/vhd"));
line = in.readLine();
while (line != null) {
int domain = -1;
-CC = gcc
-CFLAGS = -Wall -I../../xen/include -I../../xenolinux-2.4.21-sparse/include
-XI_CREATE = xi_create
-XI_START = xi_start
-XI_STOP = xi_stop
-XI_DESTROY = xi_destroy
-XI_BUILD = xi_build
-XI_PHYS_GRANT = xi_phys_grant
-XI_PHYS_REVOKE = xi_phys_revoke
-XI_PHYS_PROBE = xi_phys_probe
-
-all: $(XI_CREATE).o $(XI_START).o $(XI_STOP).o $(XI_DESTROY).o $(XI_BUILD).o \
- $(XI_PHYS_GRANT).o $(XI_PHYS_REVOKE).o $(XI_PHYS_PROBE).o
- $(CC) -o $(XI_CREATE) $(XI_CREATE).o
- $(CC) -o $(XI_BUILD) $(XI_BUILD).o
- $(CC) -o $(XI_START) $(XI_START).o
- $(CC) -o $(XI_STOP) $(XI_STOP).o
- $(CC) -o $(XI_DESTROY) $(XI_DESTROY).o
- $(CC) -o $(XI_PHYS_GRANT) $(XI_PHYS_GRANT).o
- $(CC) -o $(XI_PHYS_REVOKE) $(XI_PHYS_REVOKE).o
- $(CC) -o $(XI_PHYS_PROBE) $(XI_PHYS_PROBE).o
-
-$(XI_CREATE).o: $(XI_CREATE).c dom0_defs.h dom0_ops.h mem_defs.h
- $(CC) $(CFLAGS) -c $(XI_CREATE).c
-
-internal_domain_build.o: internal_domain_build.c dom0_defs.h dom0_ops.h mem_defs.h
- $(CC) $(CFLAGS) -c internal_domain_build.c
-
-$(XI_START).o: $(XI_START).c dom0_defs.h dom0_ops.h mem_defs.h
- $(CC) $(CFLAGS) -c $(XI_START).c
-
-$(XI_STOP).o: $(XI_STOP).c dom0_defs.h dom0_ops.h mem_defs.h
- $(CC) $(CFLAGS) -c $(XI_STOP).c
-
-$(XI_DESTROY).o: $(XI_DESTROY).c dom0_ops.h dom0_defs.h
- $(CC) $(CFLAGS) -c $(XI_DESTROY).c
-
-$(XI_PHYS_GRANT).o: $(XI_PHYS_GRANT).c
- $(CC) $(CFLAGS) -c $(XI_PHYS_GRANT).c
-
-$(XI_PHYS_REVOKE).o: $(XI_PHYS_REVOKE).c
- $(CC) $(CFLAGS) -c $(XI_PHYS_REVOKE).c
-
-$(XI_PHYS_PROBE).o: $(XI_PHYS_PROBE).c
- $(CC) $(CFLAGS) -c $(XI_PHYS_PROBE).c
+
+CC = gcc
+CFLAGS = -Wall -O3
+CFLAGS += -I../../xen/include -I../../xenolinux-2.4.21-sparse/include
+
+HDRS = $(wildcard *.h)
+SRCS = $(wildcard *.c)
+OBJS = $(patsubst %.c,%.o,$(SRCS))
+
+TARGETS = xi_create xi_start xi_stop xi_destroy xi_build
+TARGETS += xi_phys_grant xi_phys_revoke xi_phys_probe xi_list
+TARGETS += xi_sched_global xi_sched_domain xi_usage
+INSTALL = $(TARGETS) xi_vifinit xi_helper
+
+all: $(TARGETS)
install: all
- cp -a xi_list xi_vifinit xi_helper $(XI_CREATE) $(XI_BUILD) $(XI_START) $(XI_STOP) $(XI_DESTROY) $(XI_PHYSDEV_GRANT) $(XI_PHYS_REVOKE) $(XI_PHYS_PROBE).o../../../install/bin
- chmod 755 ../../../install/bin/xi_list
+ cp -a $(INSTALL) ../../../install/bin
chmod 755 ../../../install/bin/xi_vifinit
chmod 755 ../../../install/bin/xi_helper
+clean:
+ $(RM) *.o *.rpm $(TARGETS)
+
rpm: all
rm -rf staging
mkdir staging
mv staging/i386/*.rpm .
rm -rf staging
-clean:
- $(RM) *.o *.rpm $(XI_CREATE) $(XI_START) $(XI_STOP) $(XI_DESTROY) $(XI_BUILD) $(XI_PHYS_GRANT) $(XI_PHYS_REVOKE) $(XI_PHYS_PROBE)
+%: %.c $(HDRS) Makefile
+ $(CC) $(CFLAGS) -o $@ $<
-#define PROC_XENO_ROOT "xeno"
-#define PROC_CMD "dom0_cmd"
-#define PROC_DOM_PREFIX "dom"
-#define PROC_DOM_MEM "mem"
-#define PROC_DOM_DATA "new_dom_data"
-#define PROC_DOMAINS "domains"
-#define MAX_PATH 256
+#ifndef __DOM0_DEFS_H__
+#define __DOM0_DEFS_H__
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <string.h>
+
+#include <asm/types.h>
+
+#include "mem_defs.h"
+#include <asm-xeno/proc_cmd.h>
+#include <hypervisor-ifs/hypervisor-if.h>
+#include <hypervisor-ifs/dom0_ops.h>
+
+#define ERROR(_m) \
+ fprintf(stderr, "ERROR: %s\n", (_m))
+
+#define PERROR(_m) \
+ fprintf(stderr, "ERROR: %s (%d = %s)\n", (_m), errno, strerror(errno))
+
+static inline int do_privcmd(unsigned int cmd, unsigned long data)
+{
+ int fd;
+
+ if ( (fd = open("/proc/xeno/privcmd", O_RDWR)) < 0 )
+ {
+ PERROR("Could not open proc interface");
+ return -1;
+ }
+
+ if ( ioctl(fd, cmd, data) < 0 )
+ {
+#ifndef SILENT_ERRORS_FROM_XEN
+ PERROR("Error when executing privileged control ioctl");
+#endif
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
+
+static inline int xldev_to_physdev(int xldev)
+{
+ return do_privcmd(IOCTL_PRIVCMD_LINDEV_TO_XENDEV,
+ (unsigned long)xldev);
+}
+
+static inline int physdev_to_xldev(int physdev)
+{
+ return do_privcmd(IOCTL_PRIVCMD_XENDEV_TO_LINDEV,
+ (unsigned long)physdev);
+}
+
+static inline int do_xen_blkmsg(privcmd_blkmsg_t *blkmsg)
+{
+ return do_privcmd(IOCTL_PRIVCMD_BLKMSG, (unsigned long)blkmsg);
+}
+
+static inline int do_xen_hypercall(privcmd_hypercall_t *hypercall)
+{
+ return do_privcmd(IOCTL_PRIVCMD_HYPERCALL, (unsigned long)hypercall);
+}
+
+static inline int do_dom0_op(dom0_op_t *op)
+{
+ int ret = -1;
+ privcmd_hypercall_t hypercall;
+
+ hypercall.op = __HYPERVISOR_dom0_op;
+ hypercall.arg[0] = (unsigned long)op;
+
+ if ( mlock(op, sizeof(*op)) != 0 )
+ {
+ PERROR("Could not lock memory for Xen hypercall");
+ goto out1;
+ }
+
+ if ( do_xen_hypercall(&hypercall) < 0 )
+ goto out2;
+
+ ret = 0;
+
+ out2: (void)munlock(op, sizeof(*op));
+ out1: return ret;
+}
+
+static inline int do_network_op(network_op_t *op)
+{
+ int ret = -1;
+ privcmd_hypercall_t hypercall;
+
+ hypercall.op = __HYPERVISOR_network_op;
+ hypercall.arg[0] = (unsigned long)op;
+
+ if ( mlock(op, sizeof(*op)) != 0 )
+ {
+ PERROR("Could not lock memory for Xen hypercall");
+ goto out1;
+ }
+
+ if ( do_xen_hypercall(&hypercall) < 0 )
+ goto out2;
+
+ ret = 0;
+
+ out2: (void)munlock(op, sizeof(*op));
+ out1: return ret;
+}
+
+#endif /* __DOM0_DEFS_H__ */
+++ /dev/null
-
-#define NO_DOM0_OP_T
-#include "../../xen/include/hypervisor-ifs/dom0_ops.h"
-#undef NO_DOM0_OP_T
-#include "../../xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_ops.h"
-/*
- * memory related definitions needed for userspace domain builder dom0 application. these _need_ to
- * be kept in sync with the kernel .h files they were copied over from or something horrible will
- * happen. remmember: god kills a kitten every time you forget to keep these in sync.
- *
- * KAF: Boris, these constants are all fixed by x86 hardware. So the kittens are safe for now :-)
- *
- * Copyright 2002 by B Dragovic
- */
-/* copied over from hypervisor: include/asm-i386/page.h */
+#ifndef __MEM_DEFS_H__
+#define __MEM_DEFS_H__
#define _PAGE_PRESENT 0x001
-#define _PAGE_RW 0x002
-#define _PAGE_USER 0x004
-#define _PAGE_PWT 0x008
-#define _PAGE_PCD 0x010
+#define _PAGE_RW 0x002
+#define _PAGE_USER 0x004
+#define _PAGE_PWT 0x008
+#define _PAGE_PCD 0x010
#define _PAGE_ACCESSED 0x020
-#define _PAGE_DIRTY 0x040
+#define _PAGE_DIRTY 0x040
#define _PAGE_PAT 0x080
-#define _PAGE_PSE 0x080
+#define _PAGE_PSE 0x080
#define _PAGE_GLOBAL 0x100
#define l2_table_offset(_a) \
((_a) >> L2_PAGETABLE_SHIFT)
-/* local definitions */
-
-#define nr_2_page(x) ((x) << PAGE_SHIFT)
+#endif /* __MEM_DEFS_H__ */
-/*
- * XenoDomainBuilder, copyright (c) Boris Dragovic, bd240@cl.cam.ac.uk
- * This code is released under terms and conditions of GNU GPL :).
- * Usage: <executable> <mem_kb> <os image> <num_vifs>
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "asm-xeno/dom0.h"
-#include "hypervisor-ifs/hypervisor-if.h"
-#include "dom0_ops.h"
+
+#include "hypervisor-ifs/dom0_ops.h"
#include "dom0_defs.h"
#include "mem_defs.h"
-#define PERR_STRING "Xeno Domain Builder"
-
#define GUEST_SIG "XenoGues"
#define SIG_LEN 8
-/* Watch for precedence when using thses ones... */
-#define PROC_XENO_DOM0_CMD "/proc/" PROC_XENO_ROOT "/" PROC_CMD
-#define PROC_XENO_DOMAINS "/proc" PROC_XENO_ROOT "/" PROC_DOMAINS
-
-/*
- * NB. No ring-3 access in initial guestOS pagetables. Note that we allow
- * ring-3 privileges in the page directories, so that the guestOS may later
- * decide to share a 4MB region with applications.
- */
#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
-/* standardized error reporting function */
-static void dberr(char *msg)
+static long get_tot_pages(int domain_id)
{
- printf("%s: %s\n", PERR_STRING, msg);
+ dom0_op_t op;
+ op.cmd = DOM0_GETDOMAININFO;
+ op.u.getdominfo.domain = domain_id;
+ return (do_dom0_op(&op) < 0) ? -1 : op.u.getdominfo.tot_pages;
}
-/* status reporting function */
-static void dbstatus(char * msg)
+static int get_pfn_list(
+ int domain_id, unsigned long *pfn_buf, unsigned long max_pfns)
{
- printf("Domain Builder: %s\n", msg);
-}
-
+ dom0_op_t op;
+ int ret;
+ op.cmd = DOM0_GETMEMLIST;
+ op.u.getmemlist.domain = domain_id;
+ op.u.getmemlist.max_pfns = max_pfns;
+ op.u.getmemlist.buffer = pfn_buf;
+
+ if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
+ {
+ PERROR("Could not lock pfn list buffer");
+ return -1;
+ }
-/* clean up domain's memory allocations */
-static void dom_mem_cleanup(dom_mem_t * dom_mem)
-{
- int fd;
- struct dom0_unmapdommem_args argbuf;
-
- fd = open("/proc/xeno/dom0_cmd", O_WRONLY);
- if(fd < 0){
- perror("openning /proc/xeno/dom0_cmd");
- return;
- }
-
- argbuf.vaddr = dom_mem->vaddr;
- argbuf.start_pfn = dom_mem->start_pfn;
- argbuf.tot_pages = dom_mem->tot_pages;
+ ret = do_dom0_op(&op);
- if (ioctl(fd, IOCTL_DOM0_UNMAPDOMMEM, &argbuf) < 0) {
- dbstatus("Error unmapping domain's memory.\n");
- }
+ (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
- close(fd);
+ return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
}
-static int map_dom_mem(unsigned long pfn, int pages, int dom,
- dom_mem_t * dom_mem)
+static int send_pgupdates(page_update_request_t *updates, int nr_updates)
{
- struct dom0_mapdommem_args argbuf;
- int fd;
-
- argbuf.domain = dom;
- argbuf.start_pfn = pfn;
- argbuf.tot_pages = pages;
-
- fd = open("/proc/xeno/dom0_cmd", O_RDWR);
- if (fd < 0) {
- perror("openning /proc/xeno/dom0_cmd");
- return -1;
- }
-
- dom_mem->domain = dom;
- dom_mem->start_pfn = pfn;
- dom_mem->tot_pages = pages;
- dom_mem->vaddr = ioctl(fd, IOCTL_DOM0_MAPDOMMEM, &argbuf);
-
- if (dom_mem->vaddr == -1) {
- perror("mapping domain memory");
- close(fd);
- return -1;
+ int ret = -1;
+ privcmd_hypercall_t hypercall;
+
+ hypercall.op = __HYPERVISOR_pt_update;
+ hypercall.arg[0] = (unsigned long)updates;
+ hypercall.arg[1] = (unsigned long)nr_updates;
+
+ if ( mlock(updates, nr_updates * sizeof(*updates)) != 0 )
+ {
+ PERROR("Could not lock pagetable update array");
+ goto out1;
}
- close(fd);
- return 0;
+ if ( do_xen_hypercall(&hypercall) < 0 )
+ goto out2;
+
+ ret = 0;
+
+ out2: (void)munlock(updates, nr_updates * sizeof(*updates));
+ out1: return ret;
}
-/* read the kernel header, extracting the image size and load address. */
+/* Read the kernel header, extracting the image size and load address. */
static int read_kernel_header(int fd, long dom_size,
unsigned long * load_addr, size_t * ksize)
{
char signature[8];
- char status[MAX_PATH];
+ char status[1024];
struct stat stat;
- if(fstat(fd, &stat) < 0){
- perror(PERR_STRING);
+ if ( fstat(fd, &stat) < 0 )
+ {
+ PERROR("Cannot stat the kernel image");
return -1;
}
- if(stat.st_size > (dom_size << 10)){
+ if ( (stat.st_size * 2) > (dom_size << 10) )
+ {
sprintf(status, "Kernel image size %ld larger than requested "
"domain size %ld\n Terminated.\n", stat.st_size, dom_size);
- dberr(status);
+ ERROR(status);
return -1;
}
read(fd, signature, SIG_LEN);
- if(strncmp(signature, GUEST_SIG, SIG_LEN)){
- dberr("Kernel image does not contain required signature. "
+ if ( strncmp(signature, GUEST_SIG, SIG_LEN) )
+ {
+ ERROR("Kernel image does not contain required signature. "
"Terminating.\n");
return -1;
}
return 0;
}
-/* this is the main guestos setup function,
- * returnes domain descriptor structure to be used when launching
- * the domain by hypervisor to do some last minute initialization.
- * page table initialization is done by making a list of page table
- * requests that are handeled by the hypervisor in the ordinary
- * manner. this way, many potentially messy things are avoided...
- */
-#define PAGE_TO_VADDR(_pfn) ((void *)(dom_mem->vaddr + ((_pfn) * PAGE_SIZE)))
-static dom_meminfo_t *setup_guestos(int dom, int kernel_fd, int initrd_fd,
- unsigned long virt_load_addr, size_t ksize, dom_mem_t *dom_mem)
+static int devmem_fd;
+
+static int init_pfn_mapper(void)
+{
+ if ( (devmem_fd = open("/dev/mem", O_RDWR)) < 0 )
+ {
+ PERROR("Could not open /dev/mem");
+ return -1;
+ }
+ return 0;
+}
+
+static void *map_pfn(unsigned long pfn)
+{
+ void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
+ MAP_SHARED, devmem_fd, pfn << PAGE_SHIFT);
+ if ( vaddr == MAP_FAILED )
+ {
+ PERROR("Could not mmap a domain pfn using /dev/mem");
+ return NULL;
+ }
+ return vaddr;
+}
+
+static void unmap_pfn(void *vaddr)
+{
+ (void)munmap(vaddr, PAGE_SIZE);
+}
+
+static int clear_domain_page(unsigned long pfn)
+{
+ void *vaddr = map_pfn(pfn);
+ if ( vaddr == NULL )
+ return -1;
+ memset(vaddr, 0, PAGE_SIZE);
+ unmap_pfn(vaddr);
+ return 0;
+}
+
+static int copy_to_domain_page(unsigned long dst_pfn, void *src_page)
+{
+ void *vaddr = map_pfn(dst_pfn);
+ if ( vaddr == NULL )
+ return -1;
+ memcpy(vaddr, src_page, PAGE_SIZE);
+ unmap_pfn(vaddr);
+ return 0;
+}
+
+static int setup_guestos(
+ int dom, int kernel_fd, int initrd_fd, unsigned long tot_pages,
+ unsigned long virt_load_addr, size_t ksize, dom_meminfo_t *meminfo)
{
- dom_meminfo_t *meminfo = NULL;
unsigned long *page_array = NULL;
- page_update_request_t *pgt_updates = NULL;
+ page_update_request_t *pgt_update_arr = NULL, *pgt_updates = NULL;
int alloc_index, num_pt_pages;
unsigned long l2tab;
unsigned long l1tab = 0;
unsigned long num_pgt_updates = 0;
- unsigned long count, pt_start;
- struct dom0_dopgupdates_args pgupdate_req;
- int cmd_fd;
- int result;
-
- meminfo = (dom_meminfo_t *)malloc(sizeof(dom_meminfo_t));
- page_array = malloc(dom_mem->tot_pages * 4);
- if (!meminfo || !page_array) {
- dberr ("Could not allocate memory");
+ unsigned long count, pt_start, i, j;
+
+ memset(meminfo, 0, sizeof(*meminfo));
+
+ if ( init_pfn_mapper() < 0 )
+ goto error_out;
+
+ pgt_updates = malloc((tot_pages + 1024) * 3
+ * sizeof(page_update_request_t));
+ page_array = malloc(tot_pages * sizeof(unsigned long));
+ pgt_update_arr = pgt_updates;
+ if ( (pgt_update_arr == NULL) || (page_array == NULL) )
+ {
+ PERROR("Could not allocate memory");
goto error_out;
}
- pgt_updates = (page_update_request_t *)dom_mem->vaddr;
- alloc_index = dom_mem->tot_pages - 1;
- memset(meminfo, 0, sizeof(*meminfo));
+ if ( get_pfn_list(dom, page_array, tot_pages) != tot_pages )
+ {
+ PERROR("Could not get the page frame list");
+ goto error_out;
+ }
+
+ /* Load the guest OS image. */
+ for ( i = 0; i < ksize; i += PAGE_SIZE )
+ {
+ char page[PAGE_SIZE];
+ int size = ((ksize-i) < PAGE_SIZE) ? (ksize-i) : PAGE_SIZE;
+ if ( read(kernel_fd, page, size) != size )
+ {
+ PERROR("Error reading kernel image, could not"
+ " read the whole image.");
+ goto error_out;
+ }
+ copy_to_domain_page(page_array[i>>PAGE_SHIFT], page);
+ }
+
+ /* Load the initial ramdisk image. */
+ if ( initrd_fd >= 0 )
+ {
+ struct stat stat;
+ unsigned long isize;
+
+ if ( fstat(initrd_fd, &stat) < 0 )
+ {
+ PERROR("Could not stat the initrd image");
+ goto error_out;
+ }
+ isize = stat.st_size;
+ if ( ((isize + ksize) * 2) > (tot_pages << PAGE_SHIFT) )
+ {
+ ERROR("Kernel + initrd too big to safely fit in domain memory");
+ goto error_out;
+ }
- memcpy(page_array, (void *)dom_mem->vaddr, dom_mem->tot_pages * 4);
+ meminfo->virt_mod_addr = virt_load_addr + i;
+ meminfo->virt_mod_len = isize;
- /* Count bottom-level PTs, rounding up. Include one PTE for shared info. */
+ for ( j = 0; j < isize; j += PAGE_SIZE, i += PAGE_SIZE )
+ {
+ char page[PAGE_SIZE];
+ int size = ((isize-j) < PAGE_SIZE) ? (isize-j) : PAGE_SIZE;
+ if ( read(initrd_fd, page, size) != size )
+ {
+ PERROR("Error reading initrd image, could not"
+ " read the whole image.");
+ goto error_out;
+ }
+ copy_to_domain_page(page_array[i>>PAGE_SHIFT], page);
+ }
+ }
+
+ alloc_index = tot_pages - 1;
+
+ /*
+ * Count bottom-level PTs, rounding up. Include one PTE for shared info. We
+ * therefore add 1024 because 1 is for shared_info, 1023 is to round up.
+ */
num_pt_pages =
- (l1_table_offset(virt_load_addr) + dom_mem->tot_pages + 1024) / 1024;
+ (l1_table_offset(virt_load_addr) + tot_pages + 1024) / 1024;
/* We must also count the page directory. */
num_pt_pages++;
/* Index of first PT page. */
- pt_start = dom_mem->tot_pages - num_pt_pages;
+ pt_start = tot_pages - num_pt_pages;
- /* first allocate page for page dir. allocation goes backwards from the
- * end of the allocated physical address space.
+ /*
+ * First allocate page for page dir. Allocation goes backwards from the end
+ * of the allocated physical address space.
*/
- l2tab = *(page_array + alloc_index) << PAGE_SHIFT;
- memset(PAGE_TO_VADDR(alloc_index), 0, PAGE_SIZE);
+ l2tab = page_array[alloc_index] << PAGE_SHIFT;
+ if ( clear_domain_page(page_array[alloc_index]) < 0 )
+ goto error_out;
alloc_index--;
meminfo->l2_pgt_addr = l2tab;
- meminfo->virt_shinfo_addr = virt_load_addr + nr_2_page(dom_mem->tot_pages);
+ meminfo->virt_shinfo_addr = virt_load_addr + (tot_pages << PAGE_SHIFT);
- /* pin down l2tab addr as page dir page - causes hypervisor to provide
+ /*
+ * Pin down l2tab addr as page dir page - causes hypervisor to provide
* correct protection for the page
*/
pgt_updates->ptr = l2tab | PGREQ_EXTENDED_COMMAND;
* Xen during final setup.
*/
l2tab += l2_table_offset(virt_load_addr) * sizeof(l2_pgentry_t);
- for ( count = 0; count < (dom_mem->tot_pages + 1); count++ )
+ for ( count = 0; count < (tot_pages + 1); count++ )
{
if ( !((unsigned long)l1tab & (PAGE_SIZE-1)) )
{
- l1tab = *(page_array + alloc_index) << PAGE_SHIFT;
- memset(PAGE_TO_VADDR(alloc_index), 0, PAGE_SIZE);
+ l1tab = page_array[alloc_index] << PAGE_SHIFT;
+ if ( clear_domain_page(page_array[alloc_index]) < 0 )
+ goto error_out;
alloc_index--;
- l1tab += l1_table_offset(virt_load_addr + nr_2_page(count))
+ l1tab += l1_table_offset(virt_load_addr + (count << PAGE_SHIFT))
* sizeof(l1_pgentry_t);
/* make apropriate entry in the page directory */
}
/* The last PTE we consider is filled in later by Xen. */
- if ( count == dom_mem->tot_pages ) break;
+ if ( count == tot_pages ) break;
+ printf("%lu: %08lx\n", count, page_array[count]);
+
if ( count < pt_start )
{
pgt_updates->ptr = l1tab;
- pgt_updates->val = (*(page_array + count) << PAGE_SHIFT) | L1_PROT;
+ pgt_updates->val = (page_array[count] << PAGE_SHIFT) | L1_PROT;
pgt_updates++;
num_pgt_updates++;
l1tab += sizeof(l1_pgentry_t);
{
pgt_updates->ptr = l1tab;
pgt_updates->val =
- ((*(page_array + count) << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW;
+ ((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW;
pgt_updates++;
num_pgt_updates++;
l1tab += sizeof(l1_pgentry_t);
}
pgt_updates->ptr =
- (*(page_array + count) << PAGE_SHIFT) | PGREQ_MPT_UPDATE;
+ (page_array[count] << PAGE_SHIFT) | PGREQ_MPT_UPDATE;
pgt_updates->val = count;
pgt_updates++;
num_pgt_updates++;
}
- meminfo->virt_startinfo_addr = virt_load_addr + nr_2_page(alloc_index - 1);
- meminfo->domain = dom;
-
- free(page_array);
-
- /*
- * Send the page update requests down to the hypervisor.
- * NB. We must do this before loading the guest OS image!
- */
- if ( (cmd_fd = open(PROC_XENO_DOM0_CMD, O_WRONLY)) < 0 )
- {
- dberr ("Could not open " PROC_XENO_DOM0_CMD);
- goto error_out;
- }
-
- pgupdate_req.pgt_update_arr = (unsigned long)dom_mem->vaddr;
- pgupdate_req.num_pgt_updates = num_pgt_updates;
- result = ioctl(cmd_fd, IOCTL_DOM0_DOPGUPDATES, &pgupdate_req);
- close(cmd_fd);
- if (result < 0) {
- dberr ("Could not build domain page tables.");
- goto error_out;
- }
-
- /* Load the guest OS image. */
- if( read(kernel_fd, (char *)dom_mem->vaddr, ksize) != ksize )
- {
- dberr("Error reading kernel image, could not"
- " read the whole image.");
- goto error_out;
- }
-
- if( initrd_fd >= 0)
- {
- struct stat stat;
- unsigned long isize;
-
- if(fstat(initrd_fd, &stat) < 0){
- perror(PERR_STRING);
- goto error_out;
- }
- isize = stat.st_size;
-
- if( read(initrd_fd, ((char *)dom_mem->vaddr)+ksize, isize) != isize )
- {
- dberr("Error reading initrd image, could not"
- " read the whole image. Terminating.");
- goto error_out;
- }
-
- meminfo->virt_mod_addr = virt_load_addr + ksize;
- meminfo->virt_mod_len = isize;
+ printf("XHDHFDHGFGHFGXXX\n");
+ sleep(4);
- }
+ meminfo->virt_startinfo_addr =
+ virt_load_addr + ((alloc_index-1)<<PAGE_SHIFT);
+ /* Send the page update requests down to the hypervisor. */
+ if ( send_pgupdates(pgt_update_arr, num_pgt_updates) < 0 )
+ goto error_out;
- return meminfo;
+ free(page_array);
+ free(pgt_update_arr);
+ return 0;
error_out:
- if (meminfo)
- free(meminfo);
- if (page_array)
+ if ( page_array == NULL )
free(page_array);
-
- return NULL;
+ if ( pgt_update_arr == NULL )
+ free(pgt_update_arr);
+ return -1;
}
-static int launch_domain(dom_meminfo_t * meminfo)
-{
- dom0_op_t dop;
- int cmd_fd;
-
- cmd_fd = open(PROC_XENO_DOM0_CMD, O_WRONLY);
- if(cmd_fd < 0){
- perror(PERR_STRING);
- return -1;
- }
-
- dop.cmd = DOM0_BUILDDOMAIN;
- memcpy(&dop.u.meminfo, meminfo, sizeof(dom_meminfo_t));
- write(cmd_fd, &dop, sizeof(dom0_op_t));
- close(cmd_fd);
-
- return 0;
-}
-
-static int get_domain_info (int domain_id,
- int *pg_head,
- int *tot_pages)
-{
- FILE *f;
- char domains_line[256];
- int read_id;
-
- f = fopen (PROC_XENO_DOMAINS, "r");
- if (f == NULL) return -1;
-
- read_id = -1;
- while (fgets (domains_line, 256, f) != 0)
- {
- int trans;
- read_id = -1;
- trans = sscanf (domains_line, "%d %*d %*d %*d %*d %*d %x %d %*s", &read_id
- , pg_head, tot_pages);
- if (trans != 3) {
- dberr ("format of " PROC_XENO_DOMAINS " changed -- wrong kernel version?");
- read_id = -1;
- break;
- }
-
- if (read_id == domain_id) {
- break;
- }
- }
-
- fclose (f);
-
- if (read_id == -1) {
- errno = ESRCH;
- }
-
- return 0;
-}
-
-
int main(int argc, char **argv)
{
-
- dom_mem_t dom_os_image;
- dom_meminfo_t * meminfo;
+ dom0_op_t launch_op;
size_t ksize;
unsigned long load_addr;
+ long tot_pages;
int kernel_fd, initrd_fd = -1;
int count;
int cmd_len;
int args_start = 4;
char initrd_name[1024];
int domain_id;
- int pg_head;
- int tot_pages;
int rc;
- /**** this argument parsing code is really _gross_. rewrite me! ****/
-
- if(argc < 4) {
- dberr("Usage: dom_builder <domain_id> <image> <num_vifs> "
- "[<initrd=initrd_name>] <boot_params>\n");
- return -1;
+ if ( argc < 4 )
+ {
+ fprintf(stderr, "Usage: dom_builder <domain_id> <image> <num_vifs> "
+ "[<initrd=initrd_name>] <boot_params>\n");
+ return 1;
}
- /* Look up information about the domain */
domain_id = atol(argv[1]);
- if ( get_domain_info (domain_id, &pg_head, &tot_pages) != 0 )
+ if ( (tot_pages = get_tot_pages(domain_id)) < 0 )
{
- perror ("Could not find domain information");
- return -1;
+ PERROR("Could not find total pages for domain");
+ return 1;
}
-
+
kernel_fd = open(argv[2], O_RDONLY);
- if (kernel_fd < 0) {
- perror ("Could not open kernel image");
- return -1;
+ if ( kernel_fd < 0 )
+ {
+ PERROR("Could not open kernel image");
+ return 1;
}
rc = read_kernel_header(kernel_fd,
tot_pages << (PAGE_SHIFT - 10),
&load_addr, &ksize);
if ( rc < 0 )
- return -1;
+ return 1;
-
- /* map domain's memory */
- if ( map_dom_mem(pg_head, tot_pages,
- domain_id, &dom_os_image) )
- return -1;
-
if( (argc > args_start) &&
(strncmp("initrd=", argv[args_start], 7) == 0) )
{
args_start++;
initrd_fd = open(initrd_name, O_RDONLY);
- if(initrd_fd < 0){
- perror(PERR_STRING);
- return -1;
+ if ( initrd_fd < 0 )
+ {
+ PERROR("Could not open the initial ramdisk image");
+ return 1;
}
}
- /* the following code does the actual domain building */
- meminfo = setup_guestos(domain_id, kernel_fd, initrd_fd, load_addr,
- ksize, &dom_os_image);
- if (!meminfo)
- return -1;
+ if ( setup_guestos(domain_id, kernel_fd, initrd_fd, tot_pages,
+ load_addr, ksize, &launch_op.u.meminfo) < 0 )
+ return 1;
- if (initrd_fd >= 0)
+ if ( initrd_fd >= 0 )
close(initrd_fd);
close(kernel_fd);
- /* and unmap the new domain's memory image since we no longer need it */
- dom_mem_cleanup(&dom_os_image);
-
- meminfo->virt_load_addr = load_addr;
- meminfo->num_vifs = atoi(argv[3]);
- meminfo->cmd_line[0] = '\0';
+ launch_op.u.meminfo.domain = domain_id;
+ launch_op.u.meminfo.virt_load_addr = load_addr;
+ launch_op.u.meminfo.num_vifs = atoi(argv[3]);
+ launch_op.u.meminfo.cmd_line[0] = '\0';
cmd_len = 0;
- for(count = args_start; count < argc; count++){
- if(cmd_len + strlen(argv[count]) > MAX_CMD_LEN - 1){
- dberr("Size of image boot params too big!\n");
+ for ( count = args_start; count < argc; count++ )
+ {
+ if ( cmd_len + strlen(argv[count]) > MAX_CMD_LEN - 1 )
+ {
+ ERROR("Size of image boot params too big!\n");
break;
}
- strcat(meminfo->cmd_line, argv[count]);
- strcat(meminfo->cmd_line, " ");
+ strcat(launch_op.u.meminfo.cmd_line, argv[count]);
+ strcat(launch_op.u.meminfo.cmd_line, " ");
cmd_len += strlen(argv[count] + 1);
}
- /* and launch the domain */
- rc = launch_domain(meminfo);
+ launch_op.cmd = DOM0_BUILDDOMAIN;
+ rc = do_dom0_op(&launch_op);
- return 0;
+ return (rc != 0) ? 1 : 0;
}
* Usage: <executable> <mem_kb> <os image> <num_vifs>
*/
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <string.h>
-
-#include "dom0_ops.h"
+#include <hypervisor-ifs/dom0_ops.h>
#include "dom0_defs.h"
#include "mem_defs.h"
-#include "asm-xeno/dom0.h"
-
-/***********************************************************************/
static char *argv0 = "internal_domain_create";
-static void ERROR (char *message)
-{
- fprintf (stderr, "%s: %s\n", argv0, message);
- exit (-1);
-}
-
-static void PERROR (char *message)
-{
- fprintf (stderr, "%s: %s (%s)\n", argv0, message, strerror(errno));
- exit (-1);
-}
-
-/***********************************************************************/
-
static int create_new_domain(long req_mem, char *name)
{
- char cmd_path[MAX_PATH];
- int cmd_fd;
- int dom_id;
- struct dom0_createdomain_args argbuf;
+ int err;
+ dom0_op_t op;
- /* open the /proc command interface */
- sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
- cmd_fd = open(cmd_path, O_RDWR);
- if(cmd_fd < 0){
- PERROR ("Could not open PROC_CMD interface");
- return -1;
- }
+ op.cmd = DOM0_CREATEDOMAIN;
+ op.u.newdomain.memory_kb = req_mem;
+ strncpy(op.u.newdomain.name, name, MAX_DOMAIN_NAME);
+ op.u.newdomain.name[MAX_DOMAIN_NAME-1] = '\0';
- argbuf.kb_mem = req_mem;
- argbuf.name = name;
- dom_id = ioctl(cmd_fd, IOCTL_DOM0_CREATEDOMAIN, &argbuf);
- if (dom_id < 0) {
- PERROR("creating new domain");
- }
- close(cmd_fd);
- return dom_id;
-}
+ err = do_dom0_op(&op);
-/***********************************************************************/
+ return (err < 0) ? err : op.u.newdomain.domain;
+}
int main(int argc, char **argv)
{
- int dom_id;
-
- if (argv[0] != NULL)
- {
- argv0 = argv[0];
- }
-
- if(argc != 3)
- {
- fprintf (stderr, "Usage: %s <kbytes-mem> <domain-name>\n", argv0);
- return -1;
- }
-
- dom_id = create_new_domain(atol(argv[1]), argv[2]);
-
- if(dom_id < 0)
+ int dom_id;
+
+ if ( argv[0] != NULL )
+ argv0 = argv[0];
+
+ if ( argc != 3 )
{
- return -1;
+ fprintf(stderr, "Usage: %s <kbytes-mem> <domain-name>\n", argv0);
+ return 1;
}
-
- fprintf (stdout, "%d\n", dom_id);
- return 0;
+
+ dom_id = create_new_domain(atol(argv[1]), argv[2]);
+ if ( dom_id < 0 )
+ return 1;
+
+ printf("%d\n", dom_id);
+ return 0;
}
-/*
- * A very(!) simple program to kill a domain. (c) Boris Dragovic
- * Usage: <executable> <mem_kb> <os image> <num_vifs>
- */
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "dom0_ops.h"
+#include "hypervisor-ifs/dom0_ops.h"
#include "dom0_defs.h"
-
-/***********************************************************************/
+#include "mem_defs.h"
static char *argv0 = "internal_domain_stop";
-static void ERROR (char *message)
-{
- fprintf (stderr, "%s: %s\n", argv0, message);
- exit (-1);
-}
-
-static void PERROR (char *message)
-{
- fprintf (stderr, "%s: %s (%s)\n", argv0, message, strerror(errno));
- exit (-1);
-}
-
-/***********************************************************************/
-
-static int do_kill_domain(int dom_id, int force)
+static int kill_domain(int dom_id, int force)
{
- char cmd_path[MAX_PATH];
- dom0_op_t dop;
- int cmd_fd;
+ int err;
+ dom0_op_t op;
- dop.cmd = DOM0_DESTROYDOMAIN;
- dop.u.killdomain.domain = dom_id;
- dop.u.killdomain.force = force;
+ op.cmd = DOM0_DESTROYDOMAIN;
+ op.u.killdomain.domain = dom_id;
+ op.u.killdomain.force = force;
- /* open the /proc command interface */
- sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
- cmd_fd = open(cmd_path, O_WRONLY);
- if(cmd_fd < 0){
- PERROR ("Count not open PROC_CMD interface");
- }
-
- write(cmd_fd, &dop, sizeof(dom0_op_t));
- close(cmd_fd);
+ err = do_dom0_op(&op);
- return 0;
+ return (err < 0) ? -1 : 0;
}
int main(int argc, char **argv)
{
- int ret;
-
- if (argv[0] != NULL)
- {
- argv0 = argv[0];
- }
-
- if ( (argc < 2) || (argc > 3) )
+ int ret;
+
+ if ( argv[0] != NULL )
+ argv0 = argv[0];
+
+ if ( (argc < 2) || (argc > 3) )
{
usage:
fprintf(stderr, "Usage: %s [-f] <domain_id>\n", argv0);
- fprintf(stderr, " -f: Forces immediate destruction of specified domain\n");
- ret = -1;
- goto out;
+ fprintf(stderr, " -f: Forces immediate destruction of <domain_id>\n");
+ return 1;
}
-
- if ( (argc == 3) && strcmp("-f", argv[1]) ) goto usage;
-
- ret = do_kill_domain(atoi(argv[argc-1]), argc == 3);
-
-out:
- return ret;
+
+ if ( (argc == 3) && strcmp("-f", argv[1]) )
+ goto usage;
+
+ ret = kill_domain(atoi(argv[argc-1]), argc == 3);
+
+ return (ret != 0) ? 1 : 0;
}
+++ /dev/null
-#!/bin/bash
-#
-# xi_list
-#
-# This is a silly little script to dump the currently running domains.
-# The output format is a series of space-separate fields for each domain:
-#
-# 1. Domain id
-# 2. Processor
-# 3. Has CPU (1 => true, 0 => false)
-# 4. State (integer)
-# 5. State (RUNNING, INTERRUPTABLE, UNINTERRUPTABLE, WAIT, SUSPENDED, DYING)
-# 6. MCU advance
-# 7. Total pages
-# 8. Name
-
-INPUT_FILE=/proc/xeno/domains
-
-awk -f - $INPUT_FILE <<EOF
-{
- dom_id = \$1;
-
- processor = \$2;
-
- has_cpu = \$3;
-
- state = "UNKNOWN";
-
- if (\$4 == 0) state = "RUNNING";
- if (\$4 == 1) state = "INTERRUPTIBLE";
- if (\$4 == 2) state = "UNINTERRUPTABLE";
- if (\$4 == 4) state = "WAIT";
- if (\$4 == 8) state = "SUSPENDED";
- if (\$4 == 16) state = "DYING";
-
- mcu_advance = \$6;
-
- tot_pages = \$8;
-
- printf "%d %d %d %d %s %d %d %s", dom_id, processor, has_cpu, \$4, state, mcu_advance, tot_pages, \$9;
- for (i = 10; i < NF; i ++) {
- printf " %s", \$i;
- }
- printf "\n";
-}
-EOF
--- /dev/null
+/******************************************************************************
+ * xi_list.c
+ *
+ * This is a silly little program to dump the currently running domains.
+ * The output format is a series of space-separate fields for each domain:
+ *
+ * 1. Domain id
+ * 2. Processor
+ * 3. Has CPU (1 => true, 0 => false)
+ * 4. State (integer)
+ * 5. State (RUNNING, INTERRUPTIBLE, UNINTERRUPTIBLE, WAIT, SUSPENDED, DYING)
+ * 6. Pending events (hex value)
+ * 7. MCU advance
+ * 8. Total pages
+ * 9. Name
+ */
+
+/*
+ * Xen indicates when we've read info on all domains by returning error ESRCH.
+ * We don't want the helper functiosn to interpret this as a real error!
+ */
+#define SILENT_ERRORS_FROM_XEN
+
+#include "hypervisor-ifs/dom0_ops.h"
+#include "dom0_defs.h"
+#include "mem_defs.h"
+
+static char *argv0 = "internal_domain_list";
+
+static char *statestr(int state)
+{
+ switch ( state )
+ {
+ case 0: return "RUNNING";
+ case 1: return "INTERRUPTIBLE";
+ case 2: return "UNINTERRUPTIBLE";
+ case 4: return "WAIT";
+ case 8: return "SUSPENDED";
+ case 16: return "DYING";
+ default: return "UNKNOWN";
+ }
+ return NULL;
+}
+
+int main(int argc, char **argv)
+{
+ dom0_op_t op;
+
+ if ( argv[0] != NULL )
+ argv0 = argv[0];
+
+ if ( argc != 1 )
+ {
+ fprintf(stderr, "Usage: %s\n", argv0);
+ return 1;
+ }
+
+ op.cmd = DOM0_GETDOMAININFO;
+ op.u.getdominfo.domain = 0;
+ while ( do_dom0_op(&op) >= 0 )
+ {
+ printf("%8d %2d %1d %2d %s %08x %8ld %8d %s\n",
+ op.u.getdominfo.domain,
+ op.u.getdominfo.processor,
+ op.u.getdominfo.has_cpu,
+ op.u.getdominfo.state,
+ statestr(op.u.getdominfo.state),
+ op.u.getdominfo.hyp_events,
+ op.u.getdominfo.mcu_advance,
+ op.u.getdominfo.tot_pages,
+ op.u.getdominfo.name);
+ op.u.getdominfo.domain++;
+ }
+
+ return 0;
+}
-#define _GNU_SOURCE
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <sys/fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include "hypervisor-ifs/block.h"
+#define _GNU_SOURCE
+#include "dom0_defs.h"
int main(int argc, char *argv[])
{
- xp_disk_t buf;
- int fd;
- char *strbuf;
+ privcmd_blkmsg_t blkmsg;
+ xp_disk_t xpd;
- if (argc != 7) {
- fprintf(stderr,
- "Usage: xi_physdev_grant <r/rw> <domain> <device> <start sector> <n_sectors> <partition>\n");
+ if ( argc != 7 )
+ {
+ fprintf(stderr, "Usage: xi_physdev_grant <r/rw> <domain> "
+ "<device> <start sector> <n_sectors> <partition>\n");
return 1;
}
- buf.mode = 0;
- if (argv[1][0] == 'r')
- buf.mode |= 1;
- else if (argv[1][0] == 'w')
- buf.mode |= 2;
- if (argv[1][1] == 'r')
- buf.mode |= 1;
- else if (argv[1][1] == 'w')
- buf.mode |= 2;
-
- buf.device = atol(argv[3]);
- buf.start_sect = atol(argv[4]);
- buf.n_sectors = atol(argv[5]);
- buf.partition = atol(argv[6]);
-
- asprintf(&strbuf, "/proc/xeno/dom%s/phd", argv[2]);
- fd = open(strbuf, O_WRONLY);
- if (fd < 0) {
- fprintf(stderr, "Can\'t open %s: %s.\n", strbuf, strerror(errno));
- return 1;
+ xpd.mode = 0;
+ if ( strchr(argv[1], 'r') )
+ xpd.mode |= PHYSDISK_MODE_R;
+ if ( strchr(argv[1], 'w') )
+ xpd.mode |= PHYSDISK_MODE_W;
+
+ xpd.domain = atol(argv[2]);
+ xpd.device = xldev_to_physdev(atol(argv[3]));
+ xpd.start_sect = atol(argv[4]);
+ xpd.n_sectors = atol(argv[5]);
+ xpd.partition = atol(argv[6]);
+
+ if ( xpd.device == 0 )
+ {
+ ERROR("Unrecognised device");
+ return 1;
}
- free(strbuf);
- write(fd, &buf, sizeof(buf));
- close(fd);
+ blkmsg.op = XEN_BLOCK_PHYSDEV_GRANT;
+ blkmsg.buf = &xpd;
+ blkmsg.buf_size = sizeof(xpd);
+
+ if ( do_xen_blkmsg(&blkmsg) < 0 )
+ return 1;
return 0;
}
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <sys/fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include "hypervisor-ifs/block.h"
+#define _GNU_SOURCE
+#include "dom0_defs.h"
int main(int argc, char *argv[])
{
+ privcmd_blkmsg_t blkmsg;
physdisk_probebuf_t buf;
- int fd;
- int x;
- char *strbuf;
+ int i;
- if (argc != 2) {
+ if ( argc != 2 )
+ {
fprintf(stderr, "Usage: xi_phys_probe <domain_nr>\n");
return 1;
}
- asprintf(&strbuf, "/proc/xeno/dom%s/phd", argv[1]);
- fd = open(strbuf, O_RDONLY);
- if (fd < 0) {
- fprintf(stderr, "Can\'t open %s: %s.\n", strbuf, strerror(errno));
- return 1;
- }
- free(strbuf);
-
memset(&buf, 0, sizeof(buf));
- buf.n_aces = PHYSDISK_MAX_ACES_PER_REQUEST;
+
do {
- buf.n_aces = PHYSDISK_MAX_ACES_PER_REQUEST;
- read(fd, &buf, sizeof(buf));
- if (!buf.n_aces)
- break;
-
- for (x = 0; x < buf.n_aces; x++) {
- char read = (buf.entries[x].mode & 1 ? 'r' : ' ');
- char write = (buf.entries[x].mode & 2 ? 'w' : ' ');
- printf("%x %x %lx %lx %c%c\n", buf.entries[x].device,
- buf.entries[x].partition,
- buf.entries[x].start_sect,
- buf.entries[x].n_sectors, read, write);
+ buf.domain = atol(argv[1]);
+ buf.n_aces = PHYSDISK_MAX_ACES_PER_REQUEST;
+
+ blkmsg.op = XEN_BLOCK_PHYSDEV_PROBE;
+ blkmsg.buf = &buf;
+ blkmsg.buf_size = sizeof(buf);
+
+ if ( do_xen_blkmsg(&blkmsg) < 0 )
+ return 1;
+
+ for ( i = 0; i < buf.n_aces; i++ )
+ {
+ char read = (buf.entries[i].mode & 1 ? 'r' : ' ');
+ char write = (buf.entries[i].mode & 2 ? 'w' : ' ');
+ printf("%x %x %lx %lx %c%c\n",
+ physdev_to_xldev(buf.entries[i].device),
+ buf.entries[i].partition,
+ buf.entries[i].start_sect,
+ buf.entries[i].n_sectors, read, write);
}
+
buf.start_ind += buf.n_aces;
- } while (buf.n_aces == PHYSDISK_MAX_ACES_PER_REQUEST);
+ }
+ while ( buf.n_aces == PHYSDISK_MAX_ACES_PER_REQUEST );
+
return 0;
}
-#define _GNU_SOURCE
-#include <unistd.h>
-#include <errno.h>
-#include <stdio.h>
-#include <sys/fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include "hypervisor-ifs/block.h"
+#define _GNU_SOURCE
+#include "dom0_defs.h"
int main(int argc, char *argv[])
{
- xp_disk_t buf;
- int fd;
- char *strbuf;
+ privcmd_blkmsg_t blkmsg;
+ xp_disk_t xpd;
- if (argc != 5) {
- fprintf(stderr,
- "Usage: xi_physdev_revoke <domain> <device> <start sector> <n_sectors>\n");
+ if ( argc != 5 )
+ {
+ fprintf(stderr, "Usage: xi_physdev_revoke <domain> "
+ "<device> <start sector> <n_sectors>\n");
return 1;
}
- buf.device = atol(argv[2]);
- buf.mode = 0;
- buf.start_sect = atol(argv[3]);
- buf.n_sectors = atol(argv[4]);
+ xpd.mode = 0;
+ xpd.domain = atol(argv[1]);
+ xpd.device = xldev_to_physdev(atol(argv[2]));
+ xpd.start_sect = atol(argv[3]);
+ xpd.n_sectors = atol(argv[4]);
- asprintf(&strbuf, "/proc/xeno/dom%s/phd", argv[1]);
- fd = open(strbuf, O_WRONLY);
- if (fd < 0) {
- fprintf(stderr, "Can\'t open %s: %s.\n", strbuf, strerror(errno));
- return 1;
+ if ( xpd.device == 0 )
+ {
+ ERROR("Unrecognised device");
+ return 1;
}
- free(strbuf);
- write(fd, &buf, sizeof(buf));
- close(fd);
+ blkmsg.op = XEN_BLOCK_PHYSDEV_GRANT;
+ blkmsg.buf = &xpd;
+ blkmsg.buf_size = sizeof(xpd);
+
+ if ( do_xen_blkmsg(&blkmsg) < 0 )
+ return 1;
return 0;
}
--- /dev/null
+
+#include "hypervisor-ifs/dom0_ops.h"
+#include "dom0_defs.h"
+#include "mem_defs.h"
+
+static char *argv0 = "internal_domain_sched_domain";
+
+int main(int argc, char **argv)
+{
+ dom0_op_t op;
+
+ if ( argv[0] != NULL )
+ argv0 = argv[0];
+
+ if ( argc != 6 )
+ {
+ fprintf(stderr, "Usage: %s <domain> <mcu_adv> "
+ "<warp> <warpl> <warpu>\n", argv0);
+ return 1;
+ }
+
+ op.cmd = DOM0_ADJUSTDOM;
+ op.u.adjustdom.domain = atoi(argv[1]);
+ op.u.adjustdom.mcu_adv = atol(argv[1]);
+ op.u.adjustdom.warp = atol(argv[1]);
+ op.u.adjustdom.warpl = atol(argv[1]);
+ op.u.adjustdom.warpu = atol(argv[1]);
+ if ( do_dom0_op(&op) < 0 )
+ return 1;
+
+ return 0;
+}
--- /dev/null
+
+#include "hypervisor-ifs/dom0_ops.h"
+#include "dom0_defs.h"
+#include "mem_defs.h"
+
+static char *argv0 = "internal_domain_sched_global";
+
+int main(int argc, char **argv)
+{
+ dom0_op_t op;
+
+ if ( argv[0] != NULL )
+ argv0 = argv[0];
+
+ if ( argc != 2 )
+ {
+ fprintf(stderr, "Usage: %s <ctxt allowance>\n", argv0);
+ return 1;
+ }
+
+ op.cmd = DOM0_BVTCTL;
+ op.u.bvtctl.ctx_allow = atol(argv[1]);
+ if ( do_dom0_op(&op) < 0 )
+ return 1;
+
+ return 0;
+}
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <string.h>
-#include "dom0_ops.h"
+#include "hypervisor-ifs/dom0_ops.h"
#include "dom0_defs.h"
#include "mem_defs.h"
-/***********************************************************************/
-
static char *argv0 = "internal_domain_start";
-static void ERROR (char *message)
-{
- fprintf (stderr, "%s: %s\n", argv0, message);
- exit (-1);
-}
-
-static void PERROR (char *message)
-{
- fprintf (stderr, "%s: %s (%s)\n", argv0, message, strerror(errno));
- exit (-1);
-}
-
-/***********************************************************************/
-
static int start_domain(int id)
{
- char cmd_path[MAX_PATH];
- dom0_op_t dop;
- int cmd_fd;
-
- /* Set up the DOM0_STARTDOMAIN command */
- dop.cmd = DOM0_STARTDOMAIN;
- dop.u.meminfo.domain = id;
+ int err;
+ dom0_op_t op;
- /* open the /proc command interface */
- sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
- cmd_fd = open(cmd_path, O_WRONLY);
- if(cmd_fd < 0){
- PERROR ("Count not open PROC_CMD interface");
- }
+ op.cmd = DOM0_STARTDOMAIN;
+ op.u.meminfo.domain = id;
- /* Issue the command */
- write(cmd_fd, &dop, sizeof(dom0_op_t));
- close(cmd_fd);
+ err = do_dom0_op(&op);
- return 0;
+ return (err < 0) ? -1 : 0;
}
-/***********************************************************************/
-
int main(int argc, char **argv)
{
- int rc;
+ int rc;
- if (argv[0] != NULL)
- {
- argv0 = argv[0];
- }
+ if ( argv[0] != NULL )
+ argv0 = argv[0];
- if(argc != 2)
+ if ( argc != 2 )
{
- fprintf (stderr, "Usage: %s <domain-id>\n", argv0);
- return -1;
+ fprintf(stderr, "Usage: %s <domain-id>\n", argv0);
+ return 1;
}
- rc = start_domain(atol(argv[1]));
+ rc = start_domain(atol(argv[1]));
- return rc;
+ return (rc != 0) ? 1 : 0;
}
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-
-#include "dom0_ops.h"
+#include "hypervisor-ifs/dom0_ops.h"
#include "dom0_defs.h"
#include "mem_defs.h"
-/***********************************************************************/
-
static char *argv0 = "internal_domain_stop";
-static void ERROR (char *message)
-{
- fprintf (stderr, "%s: %s\n", argv0, message);
- exit (-1);
-}
-
-static void PERROR (char *message)
-{
- fprintf (stderr, "%s: %s (%s)\n", argv0, message, strerror(errno));
- exit (-1);
-}
-
-/***********************************************************************/
-
static int stop_domain(int id)
{
- dom0_newdomain_t * dom_data;
- char cmd_path[MAX_PATH];
- char dom_id_path[MAX_PATH];
- dom0_op_t dop;
- int cmd_fd;
- int id_fd;
+ int err;
+ dom0_op_t op;
- /* Set up the DOM0_STOPDOMAIN command */
- dop.cmd = DOM0_STOPDOMAIN;
- dop.u.meminfo.domain = id;
-
- /* open the /proc command interface */
- sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
- cmd_fd = open(cmd_path, O_WRONLY);
- if(cmd_fd < 0){
- PERROR ("Count not open PROC_CMD interface");
- }
+ op.cmd = DOM0_STOPDOMAIN;
+ op.u.meminfo.domain = id;
- /* Issue the command */
- write(cmd_fd, &dop, sizeof(dom0_op_t));
- close(cmd_fd);
+ err = do_dom0_op(&op);
- return 0;
+ return (err < 0) ? -1 : 0;
}
-/***********************************************************************/
-
int main(int argc, char **argv)
{
- int rc;
+ int rc;
- if (argv[0] != NULL)
- {
- argv0 = argv[0];
- }
+ if ( argv[0] != NULL )
+ argv0 = argv[0];
- if(argc != 2)
+ if ( argc != 2 )
{
- fprintf (stderr, "Usage: %s <domain-id>\n", argv0);
- return -1;
+ fprintf(stderr, "Usage: %s <domain-id>\n", argv0);
+ return 1;
}
- rc = stop_domain(atol(argv[1]));
+ rc = stop_domain(atol(argv[1]));
- return rc;
+ return (rc != 0) ? 1 : 0;
}
--- /dev/null
+
+#include "hypervisor-ifs/dom0_ops.h"
+#include "dom0_defs.h"
+#include "mem_defs.h"
+
+static char *argv0 = "internal_domain_usage";
+
+int main(int argc, char **argv)
+{
+ dom0_op_t op;
+ network_op_t netop;
+ int i, domain, vifs[32];
+
+ if ( argv[0] != NULL )
+ argv0 = argv[0];
+
+ if ( argc != 2 )
+ {
+ fprintf(stderr, "Usage: %s <domain-id>\n", argv0);
+ return 1;
+ }
+
+ domain = atol(argv[1]);
+
+ op.cmd = DOM0_GETDOMAININFO;
+ op.u.getdominfo.domain = domain;
+ if ( do_dom0_op(&op) < 0 )
+ return 1;
+
+ printf("cpu%d: %lld\n",
+ op.u.getdominfo.processor,
+ op.u.getdominfo.cpu_time);
+
+ if ( mlock(vifs, sizeof(vifs)) != 0 )
+ {
+ PERROR("Could not lock memory for network query buffer");
+ return 1;
+ }
+
+ netop.cmd = NETWORK_OP_VIFQUERY;
+ netop.u.vif_query.domain = domain;
+ netop.u.vif_query.buf = vifs;
+ if ( do_network_op(&netop) < 0 )
+ return 1;
+
+ for ( i = 1; i <= vifs[0]; i++ )
+ {
+ netop.cmd = NETWORK_OP_VIFGETINFO;
+ netop.u.vif_getinfo.domain = domain;
+ netop.u.vif_getinfo.vif = vifs[i];
+ if ( do_network_op(&netop) < 0 )
+ return 1;
+
+ printf("vif%d: sent %lld bytes (%lld packets) "
+ "received %lld bytes (%lld packets)\n",
+ vifs[i],
+ netop.u.vif_getinfo.total_bytes_sent,
+ netop.u.vif_getinfo.total_packets_sent,
+ netop.u.vif_getinfo.total_bytes_received,
+ netop.u.vif_getinfo.total_packets_received);
+ }
+
+ return 0;
+}
fi
#outbound rule:
-echo "ADD ACCEPT srcaddr=$3 srcaddrmask=255.255.255.255 srcdom=$1 srcidx=$2 dst=PHYS proto=any" > /proc/vfr
+echo "ADD ACCEPT srcaddr=$3 srcaddrmask=255.255.255.255 srcdom=$1 srcidx=$2 dst=PHYS proto=any" > /proc/xeno/vfr
#inbound rule:
-echo "ADD ACCEPT dstaddr=$3 dstaddrmask=255.255.255.255 src=ANY dstdom=$1 dstidx=$2 proto=any" > /proc/vfr
+echo "ADD ACCEPT dstaddr=$3 dstaddrmask=255.255.255.255 src=ANY dstdom=$1 dstidx=$2 proto=any" > /proc/xeno/vfr
#----] done.
ret = p->domain;
op.u.newdomain.domain = ret;
- op.u.newdomain.pg_head =
- list_entry(p->pg_head.next, struct pfn_info, list) -
- frame_table;
copy_to_user(u_dom0_op, &op, sizeof(op));
exit_create:
case DOM0_GETMEMLIST:
{
int i;
- unsigned long pfn = op.u.getmemlist.start_pfn;
+ struct task_struct * p = find_domain_by_id(op.u.getmemlist.domain);
+ unsigned long max_pfns = op.u.getmemlist.max_pfns;
+ unsigned long pfn;
unsigned long *buffer = op.u.getmemlist.buffer;
struct list_head *list_ent;
- for ( i = 0; i < op.u.getmemlist.num_pfns; i++ )
+ ret = -EINVAL;
+ if ( p != NULL )
{
- /* XXX We trust DOM0 to give us a safe buffer. XXX */
- *buffer++ = pfn;
- list_ent = frame_table[pfn].list.next;
+ list_ent = p->pg_head.next;
pfn = list_entry(list_ent, struct pfn_info, list) - frame_table;
+
+ for ( i = 0; (i < max_pfns) && (list_ent != &p->pg_head); i++ )
+ {
+ if ( put_user(pfn, buffer) )
+ {
+ ret = -EFAULT;
+ goto out_getmemlist;
+ }
+ buffer++;
+ list_ent = frame_table[pfn].list.next;
+ pfn = list_entry(list_ent, struct pfn_info, list) -
+ frame_table;
+ }
+
+ op.u.getmemlist.num_pfns = i;
+ copy_to_user(u_dom0_op, &op, sizeof(op));
+
+ ret = 0;
+
+ out_getmemlist:
+ put_task_struct(p);
}
}
break;
op.u.getdominfo.state = p->state;
op.u.getdominfo.hyp_events = p->hyp_events;
op.u.getdominfo.mcu_advance = p->mcu_advance;
- op.u.getdominfo.pg_head =
- list_entry(p->pg_head.next, struct pfn_info, list) -
- frame_table;
op.u.getdominfo.tot_pages = p->tot_pages;
op.u.getdominfo.cpu_time = p->cpu_time;
}
* userspace dom0 and final setup is being done by final_setup_guestos.
*/
int setup_guestos(struct task_struct *p, dom0_newdomain_t *params,
+ unsigned int num_vifs,
char *phy_data_start, unsigned long data_len,
char *cmdline, unsigned long initrd_len)
{
}
/* Add virtual network interfaces and point to them in startinfo. */
- while (params->num_vifs-- > 0) {
+ while (num_vifs-- > 0) {
net_vif = create_net_vif(dom);
shared_rings = net_vif->shared_rings;
if (!shared_rings) panic("no network ring!\n");
start_of_day();
/* Create initial domain 0. */
- dom0_params.num_vifs = 1;
dom0_params.memory_kb = opt_dom0_mem;
-
new_dom = do_newdomain(0, 0);
if ( new_dom == NULL ) panic("Error creating domain 0\n");
* present, is an initrd ramdisk
*/
if ( setup_guestos(new_dom,
- &dom0_params,
+ &dom0_params, 1,
(char *)MAX_DIRECTMAP_ADDRESS,
mod[mbi->mods_count-1].mod_end - mod[0].mod_start,
__va(mod[0].string),
* Copyright (c) 2002-2003, A K Warfield and K A Fraser
*/
-#include <hypervisor-ifs/network.h>
#include <xeno/sched.h>
#include <xeno/errno.h>
#include <xeno/init.h>
#include <xeno/in.h>
#include <asm/domain_page.h>
#include <asm/io.h>
+#include <hypervisor-ifs/network.h>
net_rule_ent_t *net_rule_list; /* global list of rules */
kmem_cache_t *net_vif_cache;
if ( !(p = find_domain_by_id(vq->domain)) ) {
buf[0] = -1;
copy_to_user(vq->buf, buf, sizeof(int));
- return -ENOSYS;
+ return -ESRCH;
}
for ( i = 0; i < MAX_DOMAIN_VIFS; i++ )
{
long ret=0;
network_op_t op;
-
+
if ( current->domain != 0 )
return -EPERM;
if ( copy_from_user(&op, u_network_op, sizeof(op)) )
return -EFAULT;
+
switch ( op.cmd )
{
{
ret = vif_query(&op.u.vif_query);
}
+ break;
default:
ret = -ENOSYS;
typedef struct dom0_newdomain_st
{
- unsigned int domain; // return parameter
+ /* IN parameters. */
unsigned int memory_kb;
- unsigned int num_vifs; // temporary
- unsigned long pg_head; // return parameter
char name[MAX_DOMAIN_NAME];
+ /* OUT parameters. */
+ unsigned int domain;
} dom0_newdomain_t;
typedef struct dom0_killdomain_st
typedef struct dom0_getmemlist_st
{
- unsigned long start_pfn;
+ /* IN variables. */
+ unsigned int domain;
+ unsigned long max_pfns;
+ void *buffer;
+ /* OUT variables. */
unsigned long num_pfns;
- void *buffer;
} dom0_getmemlist_t;
typedef struct domain_launch
{
- unsigned int domain;
+ unsigned int domain;
unsigned long l2_pgt_addr;
unsigned long virt_load_addr;
unsigned long virt_shinfo_addr;
typedef struct dom0_getdominfo_st
{
- unsigned int domain; /* All returns except domain */
+ /* IN variables. */
+ unsigned int domain;
+ /* OUT variables. */
char name[MAX_DOMAIN_NAME];
int processor;
int has_cpu;
int state;
int hyp_events;
unsigned long mcu_advance;
- unsigned long pg_head;
unsigned int tot_pages;
long long cpu_time;
} dom0_getdominfo_t;
unsigned int iopl;
} dom0_iopl_t;
-#ifndef NO_DOM0_OP_T
typedef struct dom0_op_st
{
unsigned long cmd;
}
u;
} dom0_op_t;
-#endif
#endif
#ifndef __RING_H__
#define __RING_H__
-#include <linux/types.h>
-
-
typedef struct tx_req_entry_st
{
unsigned short id;
extern struct task_struct *do_newdomain(unsigned int dom_id, unsigned int cpu);
extern int setup_guestos(
- struct task_struct *p, dom0_newdomain_t *params,
+ struct task_struct *p, dom0_newdomain_t *params, unsigned int num_vifs,
char *data_start, unsigned long data_len,
char *cmdline, unsigned long initrd_len);
extern int final_setup_guestos(struct task_struct *p, dom_meminfo_t *);
SUBDIRS += arch/xeno/kernel arch/xeno/mm arch/xeno/lib
SUBDIRS += arch/xeno/drivers/console arch/xeno/drivers/network
-SUBDIRS += arch/xeno/drivers/dom0 arch/xeno/drivers/block
-SUBDIRS += arch/xeno/drivers/balloon
+SUBDIRS += arch/xeno/drivers/block arch/xeno/drivers/balloon
+ifdef CONFIG_XENO_PRIV
+SUBDIRS += arch/xeno/drivers/dom0
+endif
CORE_FILES += arch/xeno/kernel/kernel.o arch/xeno/mm/mm.o
CORE_FILES += arch/xeno/drivers/console/con.o
CORE_FILES += arch/xeno/drivers/block/blk.o
CORE_FILES += arch/xeno/drivers/network/net.o
+ifdef CONFIG_XENO_PRIV
CORE_FILES += arch/xeno/drivers/dom0/dom0.o
+endif
CORE_FILES += arch/xeno/drivers/balloon/balloon_driver.o
LIBS := $(TOPDIR)/arch/xeno/lib/lib.a $(LIBS) $(TOPDIR)/arch/xeno/lib/lib.a
define_bool CONFIG_UID16 y
+mainmenu_option next_comment
+comment 'Privileged guest OS'
+bool 'Support for privileged operations (domain 0)' CONFIG_XENO_PRIV
+endmenu
+
mainmenu_option next_comment
comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
# CONFIG_SBUS is not set
CONFIG_UID16=y
+#
+# Privileged guest OS
+#
+CONFIG_XENO_PRIV=y
+
#
# Code maturity level options
#
O_TARGET := blk.o
-obj-y := xl_block.o xl_ide.o xl_scsi.o xl_segment.o xl_segment_proc.o xl_physdisk_proc.o
+obj-y := xl_block.o xl_ide.o xl_scsi.o xl_segment.o xl_segment_proc.o
include $(TOPDIR)/Rules.make
HYPERVISOR_block_io_op();
}
+
+inline kdev_t physdev_to_xldev(unsigned short physdev)
+{
+ switch (physdev & XENDEV_TYPE_MASK) {
+ case XENDEV_IDE:
+ if ( (physdev & XENDEV_IDX_MASK) < XLIDE_DEVS_PER_MAJOR) {
+ return MKDEV(XLIDE_MAJOR_0,
+ (physdev & XENDEV_IDX_MASK) << XLIDE_PARTN_SHIFT);
+ } else if ( (physdev & XENDEV_IDX_MASK) < (XLIDE_DEVS_PER_MAJOR * 2)) {
+ return MKDEV(XLIDE_MAJOR_1,
+ (physdev & XENDEV_IDX_MASK) << XLIDE_PARTN_SHIFT);
+ }
+ break;
+ case XENDEV_SCSI:
+ return MKDEV(XLSCSI_MAJOR,
+ (physdev & XENDEV_IDX_MASK) << XLSCSI_PARTN_SHIFT);
+ case XENDEV_VIRTUAL:
+ return MKDEV(XLVIRT_MAJOR,
+ (physdev & XENDEV_IDX_MASK) << XLVIRT_PARTN_SHIFT);
+ }
+
+ return 0;
+}
+
+
/* Convert from a XenoLinux major device to the Xen-level 'physical' device */
inline unsigned short xldev_to_physdev(kdev_t xldev)
{
break;
}
- if ( physdev == 0 ) BUG();
-
return physdev;
}
extern int xlsegment_hwsect(int minor);
extern struct gendisk *xlsegment_gendisk;
+extern unsigned short xldev_to_physdev(kdev_t xldev);
+extern kdev_t physdev_to_xldev(unsigned short physdev);
+
#endif /* __XL_BLOCK_H__ */
+++ /dev/null
-/* We stuff the domain number into the proc_dir_entry data pointer. */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <asm/errno.h>
-#include <linux/slab.h>
-#include <asm/hypervisor-ifs/block.h>
-#include <asm/uaccess.h>
-#include <linux/proc_fs.h>
-
-#include "xl_block.h"
-
-extern int xenolinux_control_msg(int operration, char *buffer, int size);
-extern unsigned short xldev_to_physdev(kdev_t xldev);
-
-dev_t physdev_to_xldev(unsigned short physdev)
-{
- switch (physdev & XENDEV_TYPE_MASK) {
- case XENDEV_IDE:
- if ( (physdev & XENDEV_IDX_MASK) < XLIDE_DEVS_PER_MAJOR) {
- return MKDEV(XLIDE_MAJOR_0,
- (physdev & XENDEV_IDX_MASK) << XLIDE_PARTN_SHIFT);
- } else if ( (physdev & XENDEV_IDX_MASK) < (XLIDE_DEVS_PER_MAJOR * 2)) {
- return MKDEV(XLIDE_MAJOR_1,
- (physdev & XENDEV_IDX_MASK) << XLIDE_PARTN_SHIFT);
- }
- break;
- case XENDEV_SCSI:
- return MKDEV(XLSCSI_MAJOR,
- (physdev & XENDEV_IDX_MASK) << XLSCSI_PARTN_SHIFT);
- case XENDEV_VIRTUAL:
- return MKDEV(XLVIRT_MAJOR,
- (physdev & XENDEV_IDX_MASK) << XLVIRT_PARTN_SHIFT);
- }
- printk(KERN_ALERT "Unrecognised xl device: %x\n", physdev);
- BUG();
- return -1;
-}
-
-static ssize_t proc_read_phd(struct file *file, char *buff, size_t size,
- loff_t * off)
-{
- physdisk_probebuf_t *buf;
- int res;
- struct proc_dir_entry *pde;
- int x;
-
- if (size != sizeof(physdisk_probebuf_t))
- return -EINVAL;
-
- buf = kmalloc(sizeof(physdisk_probebuf_t), GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- pde = file->f_dentry->d_inode->u.generic_ip;
- buf->domain = (int) pde->data;
-
- /* The offset reported by lseek and friends doesn't have to be in
- bytes, and it's marginally easier to say that it's in records, so
- that's what we do. */
- buf->start_ind = *off;
- res = xenolinux_control_msg(XEN_BLOCK_PHYSDEV_PROBE, (void *) buf,
- sizeof(physdisk_probebuf_t));
- *off += buf->n_aces;
-
- if (res)
- res = -EINVAL;
- else {
- for (x = 0; x < buf->n_aces; x++)
- buf->entries[x].device =
- physdev_to_xldev(buf->entries[x].device);
- res = sizeof(physdisk_probebuf_t);
- if (copy_to_user(buff, buf, sizeof(physdisk_probebuf_t))) {
- res = -EFAULT;
- }
- }
- kfree(buf);
- return res;
-}
-
-static int proc_write_phd(struct file *file, const char *buffer,
- size_t count, loff_t * ignore)
-{
- char *local;
- int res;
- xp_disk_t *xpd;
- struct proc_dir_entry *pde;
-
- if (count != sizeof(xp_disk_t))
- return -EINVAL;
-
- local = kmalloc(count + 1, GFP_KERNEL);
- if (!local)
- return -ENOMEM;
- if (copy_from_user(local, buffer, count)) {
- res = -EFAULT;
- goto out;
- }
-
- xpd = (xp_disk_t *) local;
-
- pde = file->f_dentry->d_inode->u.generic_ip;
- xpd->domain = (int) pde->data;
- xpd->device = xldev_to_physdev(xpd->device);
-
- res = xenolinux_control_msg(XEN_BLOCK_PHYSDEV_GRANT, local, count);
- if (res == 0)
- res = count;
- else
- res = -EINVAL;
- out:
- kfree(local);
- return res;
-}
-
-struct file_operations dom0_phd_fops = {
- read:proc_read_phd,
- write:proc_write_phd
-};
static struct proc_dir_entry *vhd;
-extern unsigned short xldev_to_physdev(kdev_t xldev);
-extern dev_t physdev_to_xldev(unsigned short physdev);
-
static void *proc_vhd_next(struct seq_file *s, void *v, loff_t *pos)
{
xen_segment_info_t *data;
int __init xlseg_proc_init(void)
{
- vhd = create_proc_entry("xeno/dom0/vhd", 0600, NULL);
- if (vhd == NULL)
- {
+ if ( !(start_info.flags & SIF_PRIVILEGED) )
+ return 0;
+
+ vhd = create_proc_entry("xeno/vhd", 0600, NULL);
+ if ( vhd == NULL )
panic ("xlseg_init: unable to create vhd proc entry\n");
- }
+
vhd->data = NULL;
vhd->proc_fops = &proc_vhd_operations;
vhd->owner = THIS_MODULE;
O_TARGET := dom0.o
-obj-y := dom0_memory.o dom0_core.o vfr.o sched_ops.o
+obj-y := dom0_core.o vfr.o
include $(TOPDIR)/Rules.make
+++ /dev/null
-/*
- * domain 0 block driver interface
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-
-static int __init init_module(void)
-{
- request_module("xl_block");
- printk("Successfully installed domain 0 block interface\n");
-
-
- return 0;
-}
-
-static void __exit cleanup_module(void)
-{
- printk("Successfully de-installed domain-0 block interface\n");
- return 0;
-}
-
-module_init(init_module);
-module_exit(cleanup_module);
*
* Interface to privileged domain-0 commands.
*
- * Copyright (c) 2002, K A Fraser, B Dragovic
+ * Copyright (c) 2002-2003, K A Fraser, B Dragovic
*/
#include <linux/config.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/proc_fs.h>
-
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/swap.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
#include <asm/tlb.h>
-#include <asm/dom0.h>
-
-#include "dom0_ops.h"
-
-#define MAP_DISCONT 1
+#include <asm/proc_cmd.h>
+#include <asm/hypervisor-ifs/dom0_ops.h>
-/* Private proc-file data structures. */
-typedef struct proc_data {
- unsigned int domain;
- unsigned long map_size;
-} dom_procdata_t;
-
-/* XXX this certainly shouldn't be here. */
-extern struct file_operations dom0_phd_fops;
+#include "../block/xl_block.h"
struct proc_dir_entry *xeno_base;
-static struct proc_dir_entry *dom0_cmd_intf;
-static struct proc_dir_entry *dom_list_intf;
+static struct proc_dir_entry *privcmd_intf;
-int direct_unmap(struct mm_struct *, unsigned long, unsigned long);
-unsigned long direct_mmap(unsigned long phys_addr, unsigned long size,
- pgprot_t prot, int flag, int tot_pages);
-struct list_head * find_direct(struct list_head *, unsigned long);
-static ssize_t dom_usage_read(struct file * file, char * buff, size_t size, loff_t * off)
+static int privcmd_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long data)
{
- char str[256];
- int vifs[32];
- dom0_op_t op;
- network_op_t netop;
- int i, end;
- unsigned int domain;
- static int finished = 0;
+ int ret = 0;
- if ( finished )
+ switch ( cmd )
{
- finished = 0;
- return 0;
- }
-
- domain = (unsigned int)
- ((struct proc_dir_entry *)file->f_dentry->d_inode->u.generic_ip)->data;
- op.cmd = DOM0_GETDOMAININFO;
-
- op.u.getdominfo.domain = domain;
-
- (void) HYPERVISOR_dom0_op(&op);
-
- end = snprintf(str, 256, "cpu: %lld\n", op.u.getdominfo.cpu_time);
-
- netop.cmd = NETWORK_OP_VIFQUERY;
- netop.u.vif_query.domain = domain;
- netop.u.vif_query.buf = vifs;
-
- (void) HYPERVISOR_network_op(&netop);
-
- for(i = 1; i <= vifs[0]; i++) {
- netop.cmd = NETWORK_OP_VIFGETINFO;
- netop.u.vif_getinfo.domain = domain;
- netop.u.vif_getinfo.vif = vifs[i];
-
- (void) HYPERVISOR_network_op(&netop);
-
- end += snprintf(str + end, 255 - end,
- "vif%d: sent %lld bytes (%lld packets) "
- "received %lld bytes (%lld packets)\n",
- vifs[i],
- netop.u.vif_getinfo.total_bytes_sent,
- netop.u.vif_getinfo.total_packets_sent,
- netop.u.vif_getinfo.total_bytes_received,
- netop.u.vif_getinfo.total_packets_received);
- }
-
- if (*off >= end + 1) return 0;
-
- copy_to_user(buff, str, end);
-
- finished = 1;
-
- return end + 1;
-}
-
-static struct file_operations dom_usage_ops = {
- read: dom_usage_read
-};
-
-
-static void create_proc_dom_entries(int dom)
-{
- struct proc_dir_entry * dir;
- dom_procdata_t * dom_data;
- char dir_name[16];
- struct proc_dir_entry * file;
-
- sprintf(dir_name, "dom%d", dom);
-
- dom_data = (dom_procdata_t *)kmalloc(sizeof(dom_procdata_t), GFP_KERNEL);
- dom_data->domain = dom;
-
- dir = proc_mkdir(dir_name, xeno_base);
- dir->data = dom_data;
-
- file = create_proc_entry("usage", 0600, dir);
- if (file != NULL)
+ case IOCTL_PRIVCMD_HYPERCALL:
{
- file->owner = THIS_MODULE;
- file->nlink = 1;
- file->proc_fops = &dom_usage_ops;
- file->data = (void *) dom;
+ privcmd_hypercall_t hypercall;
+ if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) )
+ return -EFAULT;
+ __asm__ __volatile__ (
+ "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; "
+ "movl 4(%%eax),%%ebx ;"
+ "movl 8(%%eax),%%ecx ;"
+ "movl 12(%%eax),%%edx ;"
+ "movl 16(%%eax),%%esi ;"
+ "movl 20(%%eax),%%edi ;"
+ "movl (%%eax),%%eax ;"
+ TRAP_INSTR "; "
+ "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx"
+ : "=a" (ret) : "0" (&hypercall) : "memory" );
}
+ break;
- file = create_proc_entry("phd", 0600, dir);
- if (file != NULL)
+ case IOCTL_PRIVCMD_BLKMSG:
{
- file->owner = THIS_MODULE;
- file->nlink = 1;
- file->proc_fops = &dom0_phd_fops;
- file->data = (void *) dom;
+ privcmd_blkmsg_t blkmsg;
+ char *kbuf;
+ int ret;
+ if ( copy_from_user(&blkmsg, (void *)data, sizeof(blkmsg)) )
+ return -EFAULT;
+ if ( blkmsg.buf_size > PAGE_SIZE )
+ return -EINVAL;
+ if ( (kbuf = kmalloc(blkmsg.buf_size, GFP_KERNEL)) == NULL )
+ return -ENOMEM;
+ if ( copy_from_user(kbuf, blkmsg.buf, blkmsg.buf_size) ) {
+ kfree(kbuf);
+ return -EFAULT;
+ }
+ ret = xenolinux_control_msg((int)blkmsg.op, kbuf, blkmsg.buf_size);
+ if ( ret != 0 ) {
+ kfree(kbuf);
+ return ret;
+ }
+ if ( copy_to_user(blkmsg.buf, kbuf, blkmsg.buf_size) ) {
+ kfree(kbuf);
+ return -EFAULT;
+ }
+ kfree(kbuf);
}
-}
-
-/***********************************************************************
- *
- * Implementation of /proc/xeno/domains
- */
-
-static dom0_op_t proc_domains_op;
-static int proc_domains_finished;
-static DECLARE_MUTEX(proc_xeno_domains_lock);
-
-static void *xeno_domains_next(struct seq_file *s, void *v, loff_t *pos)
-{
- int ret;
+ break;
+
+ case IOCTL_PRIVCMD_LINDEV_TO_XENDEV:
+ ret = (int)xldev_to_physdev((kdev_t)data);
- if ( pos != NULL )
- ++(*pos);
+ case IOCTL_PRIVCMD_XENDEV_TO_LINDEV:
+ ret = (int)physdev_to_xldev((unsigned short)data);
- if ( !proc_domains_finished )
+ default:
{
- proc_domains_op.u.getdominfo.domain++;
- ret = HYPERVISOR_dom0_op(&proc_domains_op);
- if ( ret < 0 )
- proc_domains_finished = 1;
+ ret = -EINVAL;
}
-
- return (proc_domains_finished) ? NULL : &proc_domains_op;
-}
-
-static void *xeno_domains_start(struct seq_file *s, loff_t *ppos)
-{
- loff_t pos = *ppos;
-
- down (&proc_xeno_domains_lock);
- proc_domains_op.cmd = DOM0_GETDOMAININFO;
- proc_domains_op.u.getdominfo.domain = 0;
- (void)HYPERVISOR_dom0_op(&proc_domains_op);
- proc_domains_finished = 0;
-
- while (pos > 0) {
- pos --;
- xeno_domains_next (s, NULL, NULL);
+ break;
}
-
- return (proc_domains_finished) ? NULL : &proc_domains_op;
-}
-static void xeno_domains_stop(struct seq_file *s, void *v)
-{
- up(&proc_xeno_domains_lock);
+ return ret;
}
-static int xeno_domains_show(struct seq_file *s, void *v)
-{
- dom0_op_t *di = v;
-
- /*
- * Output one domain's details to dom0.
- *
- * If you update this format string then change xi_list to match.
- */
-
- seq_printf (s,
- "%8d %2d %1d %2d %8d %8ld %p %8d %s\n",
- di -> u.getdominfo.domain,
- di -> u.getdominfo.processor,
- di -> u.getdominfo.has_cpu,
- di -> u.getdominfo.state,
- di -> u.getdominfo.hyp_events,
- di -> u.getdominfo.mcu_advance,
- (void *)di -> u.getdominfo.pg_head,
- di -> u.getdominfo.tot_pages,
- di -> u.getdominfo.name);
-
- return 0;
-}
-static struct seq_operations xeno_domains_op = {
- .start = xeno_domains_start,
- .next = xeno_domains_next,
- .stop = xeno_domains_stop,
- .show = xeno_domains_show,
+static struct file_operations privcmd_file_ops = {
+ ioctl : privcmd_ioctl
};
-static int xeno_domains_open(struct inode *inode, struct file *file)
-{
- return seq_open(file, &xeno_domains_op);
-}
-
-static struct file_operations proc_xeno_domains_operations = {
- open: xeno_domains_open,
- read: seq_read,
- llseek: seq_lseek,
- release: seq_release,
-};
-
-/***********************************************************************
- *
- * Implementation of /proc/xeno/dom0_cmd
- */
-
-static int dom0_cmd_write(struct file *file, const char *buffer, size_t size,
- loff_t *off)
-{
- dom0_op_t op;
-
- copy_from_user(&op, buffer, sizeof(dom0_op_t));
-
- return HYPERVISOR_dom0_op(&op);
-}
-
-static int handle_dom0_cmd_createdomain(unsigned long data)
-{
- struct dom0_createdomain_args argbuf;
- int namelen;
- dom0_op_t op;
- int ret;
-
- if (copy_from_user(&argbuf, (void *)data, sizeof(argbuf)))
- return -EFAULT;
-
- op.cmd = DOM0_CREATEDOMAIN;
- op.u.newdomain.domain = -666;
- op.u.newdomain.memory_kb = argbuf.kb_mem;
- op.u.newdomain.num_vifs = 0; /* Not used anymore -- it's done in
- BUILDDOMAIN. */
- namelen = strnlen_user(argbuf.name, MAX_DOMAIN_NAME);
- if (copy_from_user(op.u.newdomain.name, argbuf.name, namelen + 1))
- return -EFAULT;
-
- /* Error checking? The old code deosn't appear to do any, and I
- can't see where the return values are documented... */
- ret = HYPERVISOR_dom0_op(&op);
-
- if (op.u.newdomain.domain == -666) {
- /* HACK: We use this to detect whether the create actually
- succeeded, because Xen doesn't appear to want to tell us... */
-
- /* The only time I've actually got this to happen was when trying
- to create a domain with more memory than is actually in the
- machine, so we guess the error code is ENOMEM. */
- return -ENOMEM;
- }
-
- /* Create proc entries */
- ret = op.u.newdomain.domain;
- create_proc_dom_entries(ret);
-
- return ret;
-}
-
-static unsigned long handle_dom0_cmd_mapdommem(unsigned long data)
-{
- struct dom0_mapdommem_args argbuf;
-
- if (copy_from_user(&argbuf, (void *)data, sizeof(argbuf)))
- return -EFAULT;
-
- return direct_mmap(argbuf.start_pfn << PAGE_SHIFT,
- argbuf.tot_pages << PAGE_SHIFT,
- PAGE_SHARED,
- MAP_DISCONT,
- argbuf.tot_pages);
-}
-
-static int handle_dom0_cmd_unmapdommem(unsigned long data)
-{
- struct dom0_unmapdommem_args argbuf;
-
- if (copy_from_user(&argbuf, (void *)data, sizeof(argbuf)))
- return -EFAULT;
-
- return direct_unmap(current->mm, argbuf.vaddr,
- argbuf.tot_pages << PAGE_SHIFT);
-}
-
-static int handle_dom0_cmd_dopgupdates(unsigned long data)
-{
- struct dom0_dopgupdates_args argbuf;
- struct list_head *entry;
- direct_mmap_node_t *node;
-
- if (copy_from_user(&argbuf, (void *)data, sizeof(argbuf)))
- return -EFAULT;
-
- /* argbuf.pgt_update_arr had better be direct mapped... */
- /* Actually, we only *really* need to make sure that all of it's
- pages are in memory and aren't going to get swapped out in the
- mean time, but this is slightly easier than checking all of
- that and is sufficient for the current userspace tools. */
- entry = find_direct(¤t->mm->context.direct_list,
- argbuf.pgt_update_arr);
- if (entry == ¤t->mm->context.direct_list)
- return -EINVAL;
- node = list_entry(entry, direct_mmap_node_t, list);
- if (node->vm_start > argbuf.pgt_update_arr ||
- node->vm_end <= argbuf.pgt_update_arr * sizeof(page_update_request_t))
- return -EINVAL;
-
- return HYPERVISOR_pt_update((void *)argbuf.pgt_update_arr,
- argbuf.num_pgt_updates);
-}
-
-static int dom0_cmd_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long data)
-{
- switch (cmd) {
- case IOCTL_DOM0_CREATEDOMAIN:
- return handle_dom0_cmd_createdomain(data);
- case IOCTL_DOM0_MAPDOMMEM:
- return handle_dom0_cmd_mapdommem(data);
- case IOCTL_DOM0_UNMAPDOMMEM:
- return handle_dom0_cmd_unmapdommem(data);
- case IOCTL_DOM0_DOPGUPDATES:
- return handle_dom0_cmd_dopgupdates(data);
- default:
- return -ENOTTY; /* It isn't obvious why this is the correct error
- code when an ioctl isn't recognised, but it
- does appear to be what's used in the rest of
- the kernel. */
- }
-}
-
-/***********************************************************************/
-
-
-static struct file_operations dom0_cmd_file_ops = {
- write : dom0_cmd_write,
- ioctl : dom0_cmd_ioctl
-};
static int __init init_module(void)
{
+ if ( !(start_info.flags & SIF_PRIVILEGED) )
+ return 0;
+
/* xeno proc root setup */
xeno_base = proc_mkdir("xeno", &proc_root);
/* xeno control interface */
- dom0_cmd_intf = create_proc_entry("dom0_cmd", 0600, xeno_base);
-
- if ( dom0_cmd_intf != NULL )
+ privcmd_intf = create_proc_entry("privcmd", 0400, xeno_base);
+ if ( privcmd_intf != NULL )
{
- dom0_cmd_intf->owner = THIS_MODULE;
- dom0_cmd_intf->nlink = 1;
- dom0_cmd_intf->proc_fops = &dom0_cmd_file_ops;
+ privcmd_intf->owner = THIS_MODULE;
+ privcmd_intf->nlink = 1;
+ privcmd_intf->proc_fops = &privcmd_file_ops;
}
- /* domain list interface */
- dom_list_intf = create_proc_entry("domains", 0400, xeno_base);
- if ( dom_list_intf != NULL )
- {
- dom_list_intf->owner = THIS_MODULE;
- dom_list_intf->nlink = 1;
- dom_list_intf->proc_fops = &proc_xeno_domains_operations;
- }
-
- /* set up /proc entries for dom 0 */
- create_proc_dom_entries(0);
-
return 0;
}
static void __exit cleanup_module(void)
{
- if ( dom0_cmd_intf == NULL ) return;
- remove_proc_entry("dom0", &proc_root);
- dom0_cmd_intf = NULL;
+ if ( privcmd_intf == NULL ) return;
+ remove_proc_entry("xeno", &proc_root);
+ privcmd_intf = NULL;
}
+++ /dev/null
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/mman.h>
-#include <linux/swap.h>
-#include <linux/smp_lock.h>
-#include <linux/swapctl.h>
-#include <linux/iobuf.h>
-#include <linux/highmem.h>
-#include <linux/pagemap.h>
-#include <linux/list.h>
-
-#include <asm/pgalloc.h>
-#include <asm/uaccess.h>
-#include <asm/tlb.h>
-#include <asm/mmu.h>
-
-#include "dom0_ops.h"
-
-#define MAP_CONT 0
-#define MAP_DISCONT 1
-
-extern struct list_head * find_direct(struct list_head *, unsigned long);
-extern int direct_remap_area_pages(struct mm_struct *, unsigned long,
- unsigned long, unsigned long, pgprot_t);
-extern void direct_zap_page_range(struct mm_struct *, unsigned long,
- unsigned long);
-
-/*
- * used for remapping discontiguous bits of domain's memory, pages to map are
- * found from frame table beginning at the given first_pg index
- */
-int direct_remap_disc_page_range(unsigned long from,
- unsigned long first_pg,
- int tot_pages,
- pgprot_t prot)
-{
- dom0_op_t dom0_op;
- unsigned long *pfns = (unsigned long *)get_free_page(GFP_KERNEL);
- unsigned long start = from;
- int pages, i;
-
- while ( tot_pages != 0 )
- {
- dom0_op.cmd = DOM0_GETMEMLIST;
- dom0_op.u.getmemlist.start_pfn = first_pg;
- pages = 1023;
- dom0_op.u.getmemlist.num_pfns = 1024;
- if ( tot_pages < 1024 )
- dom0_op.u.getmemlist.num_pfns = pages = tot_pages;
- dom0_op.u.getmemlist.buffer = pfns;
- (void)HYPERVISOR_dom0_op(&dom0_op);
- first_pg = pfns[1023];
-
- for ( i = 0; i < pages; i++ )
- {
- if(direct_remap_area_pages(current->mm,
- start, pfns[i] << PAGE_SHIFT,
- PAGE_SIZE, prot))
- goto out;
- start += PAGE_SIZE;
- tot_pages--;
- }
- }
-
- out:
- free_page((unsigned long)pfns);
- return tot_pages;
-}
-
-
-unsigned long direct_mmap(unsigned long phys_addr, unsigned long size,
- pgprot_t prot, int flag, int tot_pages)
-{
- direct_mmap_node_t * dmmap;
- struct list_head * entry;
- unsigned long addr;
- int ret = 0;
-
- if(!capable(CAP_SYS_ADMIN)){
- ret = -EPERM;
- goto out;
- }
-
- /* get unmapped area invokes xen specific arch_get_unmapped_area */
- addr = get_unmapped_area(NULL, 0, size, 0, 0);
- if(addr & ~PAGE_MASK){
- ret = -ENOMEM;
- goto out;
- }
-
- /* add node on the list of directly mapped areas, make sure the
- * list remains sorted.
- */
- dmmap = (direct_mmap_node_t *)kmalloc(sizeof(direct_mmap_node_t), GFP_KERNEL);
- dmmap->vm_start = addr;
- dmmap->vm_end = addr + size;
- entry = find_direct(¤t->mm->context.direct_list, addr);
- if(entry != ¤t->mm->context.direct_list){
- list_add_tail(&dmmap->list, entry);
- } else {
- list_add_tail(&dmmap->list, ¤t->mm->context.direct_list);
- }
-
- /* and perform the mapping */
- if(flag == MAP_DISCONT){
- ret = direct_remap_disc_page_range(addr, phys_addr >> PAGE_SHIFT,
- tot_pages, prot);
- } else {
- ret = direct_remap_area_pages(current->mm,
- addr, phys_addr, size, prot);
- }
-
- if(ret == 0)
- ret = addr;
-
- out:
- return ret;
-}
-
-
-int direct_unmap(struct mm_struct *mm, unsigned long addr, unsigned long size)
-{
- int count = 0, tot_pages = (size+PAGE_SIZE-1) >> PAGE_SHIFT;
- direct_mmap_node_t * node;
- struct list_head * curr;
- struct list_head * direct_list = &mm->context.direct_list;
-
- curr = direct_list->next;
- while ( curr != direct_list )
- {
- node = list_entry(curr, direct_mmap_node_t, list);
- if ( node->vm_start == addr )
- break;
- curr = curr->next;
- }
-
- if ( curr == direct_list )
- return -1;
-
- list_del(&node->list);
- kfree(node);
-
- while ( count < tot_pages )
- {
- direct_zap_page_range(mm, addr, PAGE_SIZE);
- addr += PAGE_SIZE;
- count++;
- }
-
- return 0;
-}
+++ /dev/null
-/******************************************************************************
- * dom0_ops.h
- *
- * Process command requests from domain-0 guest OS.
- * This file includes the Xen part of the interface, plus the extra stuff
- * that is dealt with by Xenolinux without being handed down to Xen.
- *
- * Copyright (c) 2002-2003, K A Fraser, B Dragovic
- */
-
-#ifndef __DOM0_DOM0_OPS_H__
-#define __DOM0_DOM0_OPS_H__
-
-/* External users of this header file will include Xen's version separately. */
-#ifdef __KERNEL__
-#define NO_DOM0_OP_T
-#include <asm/hypervisor-ifs/dom0_ops.h>
-#endif
-
-/* Extra commands dealt with by Xenolinux. */
-#define MAP_DOM_MEM 1014
-#define DO_PGUPDATES 1015
-
-typedef struct dom_mem
-{
- unsigned int domain;
- unsigned long vaddr;
- unsigned long start_pfn;
- int tot_pages;
-} dom_mem_t;
-
-typedef struct dom_pgupdate
-{
- unsigned long pgt_update_arr;
- unsigned long num_pgt_updates;
-} dom_pgupdate_t;
-
-typedef struct dom0_op_st
-{
- unsigned long cmd;
- union
- {
- dom0_newdomain_t newdomain;
- dom0_killdomain_t killdomain;
- dom0_getmemlist_t getmemlist;
- dom0_bvtctl_t bvtctl;
- dom0_adjustdom_t adjustdom;
- dom_mem_t dommem;
- dom_pgupdate_t pgupdate;
- dom_meminfo_t meminfo;
- dom0_getdominfo_t getdominfo;
- dom0_iopl_t iopl;
- } u;
-} dom0_op_t;
-
-#endif /* __DOM0_DOM0_OPS_H__ */
+++ /dev/null
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
- ****************************************************************************
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- ****************************************************************************
- *
- * File: sched_ops.c
- * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Changes:
- *
- * Date: Mar 2003
- *
- * Environment: XenoLinux
- * Description: Dom0 Control interface to scheduler in Xen
- *
- * code based on Andy's vfr parsing code
- *
- * Commands understood by the interface:
- *
- * C <context swith allowance>
- * S <did> <mcu advance> <warp> <warp limit> <unwarp limit>
- *
- ****************************************************************************
- * $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
- ****************************************************************************
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/proc_fs.h>
-
-#include "dom0_ops.h"
-
-#define SCHED_ENTRY "sched"
-extern struct proc_dir_entry *xeno_base;
-static struct proc_dir_entry *sched_pde;
-
-static unsigned char readbuf[1024];
-
-static int sched_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- strcpy(page, readbuf);
- *readbuf = '\0';
- *eof = 1;
- *start = page;
- return strlen(page);
-}
-
-
-static int sched_write_proc(struct file *file, const char *buffer,
- u_long count, void *data)
-{
- dom0_op_t op;
-
- int ret, len;
- int ts, te, tl; /* token start, end, and length */
-
- /* Only admin can adjust scheduling parameters */
- if ( !capable(CAP_SYS_ADMIN) )
- return -EPERM;
-
- /* parse the commands */
- len = count;
- ts = te = 0;
-
- while ( count && isspace(buffer[ts]) ) { ts++; count--; } /*skip spaces*/
- te = ts;
- while ( count && !isspace(buffer[te]) ) { te++; count--; } /*command end*/
- if ( te <= ts ) goto bad;
- tl = te - ts;
-
- if ( strncmp(&buffer[ts], "C", tl) == 0 ) {
- op.cmd = DOM0_BVTCTL;
- } else if ( strncmp(&buffer[ts], "S", tl) == 0 ) {
- op.cmd = DOM0_ADJUSTDOM;
- } else
- goto bad;
-
- /* skip whitspaces and get first parameter */
- ts = te; while ( count && isspace(buffer[ts]) ) { ts++; count--; }
- te = ts; while ( count && !isspace(buffer[te]) ) { te++; count--; }
- if ( te <= ts ) goto bad;
- tl = te - ts;
- if ( !isdigit(buffer[ts]) ) goto bad;
-
- if (op.cmd == DOM0_BVTCTL) {
- /* get context switch allowance */
- sscanf(&buffer[ts], "%lu", &op.u.bvtctl.ctx_allow);
- } else if (op.cmd == DOM0_ADJUSTDOM) {
- sscanf(&buffer[ts], "%u %lu %lu %lu %lu",
- &op.u.adjustdom.domain,
- &op.u.adjustdom.mcu_adv,
- &op.u.adjustdom.warp,
- &op.u.adjustdom.warpl,
- &op.u.adjustdom.warpu);
- }
- ret = HYPERVISOR_dom0_op(&op);
- return sizeof(op);
-
- bad:
- return -EINVAL;
-
-}
-
-
-/*
- * main scheduler interface driver driver initialization function.
- */
-static int __init init_module(void)
-{
- printk(KERN_ALERT "Starting Domain Scheduler Control Interface\n");
-
- sched_pde = create_proc_entry(SCHED_ENTRY, 0600, xeno_base);
- if ( sched_pde == NULL )
- {
- printk(KERN_ALERT "Unable to create dom scheduler proc entry!");
- return -1;
- }
-
- sched_pde->read_proc = sched_read_proc;
- sched_pde->write_proc = sched_write_proc;
-
- return 0;
-}
-
-static void __exit cleanup_module(void)
-{
-}
-
-module_init(init_module);
-module_exit(cleanup_module);
-
static int __init init_module(void)
{
*readbuf = '\0';
- proc_vfr = create_proc_entry ("vfr", 0600, &proc_root);
+ proc_vfr = create_proc_entry ("xeno/vfr", 0600, &proc_root);
if ( proc_vfr != NULL )
{
proc_vfr->owner = THIS_MODULE;
static void __exit cleanup_module(void)
{
if ( proc_vfr == NULL ) return;
- remove_proc_entry("vfr", &proc_root);
+ remove_proc_entry("xeno/vfr", &proc_root);
proc_vfr = NULL;
}
flush_page_update_queue();
vfree(ldt);
}
-
- /* YUK! We do this here because destroy_context() is too late. */
- destroy_direct_list(mm);
}
/*
O_TARGET := mm.o
-obj-y := init.o fault.o extable.o pageattr.o hypervisor.o get_unmapped_area.o ioremap.o
+obj-y := init.o fault.o extable.o pageattr.o hypervisor.o ioremap.o
export-objs := pageattr.o
+++ /dev/null
-
-#include <linux/slab.h>
-#include <linux/shm.h>
-#include <linux/mman.h>
-#include <linux/pagemap.h>
-#include <linux/swap.h>
-#include <linux/swapctl.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/personality.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgalloc.h>
-
-extern int direct_unmap(struct mm_struct *, unsigned long, unsigned long);
-
-int init_direct_list(struct mm_struct *mm)
-{
- INIT_LIST_HEAD(&mm->context.direct_list);
- return 0;
-}
-
-
-void destroy_direct_list(struct mm_struct *mm)
-{
- struct list_head *curr, *direct_list = &mm->context.direct_list;
- while ( (curr = direct_list->next) != direct_list )
- {
- direct_mmap_node_t *node = list_entry(curr, direct_mmap_node_t, list);
- if ( direct_unmap(mm, node->vm_start, node->vm_end - node->vm_start) )
- BUG();
- }
-}
-
-
-struct list_head *find_direct(struct list_head *list, unsigned long addr)
-{
- struct list_head * curr;
- struct list_head * direct_list = ¤t->mm->context.direct_list;
- direct_mmap_node_t * node;
-
- for ( curr = direct_list->next; curr != direct_list; curr = curr->next )
- {
- node = list_entry(curr, direct_mmap_node_t, list);
- if ( node->vm_start >= addr ) break;
- }
-
- return curr;
-}
-
-
-unsigned long arch_get_unmapped_area(struct file *filp,
- unsigned long addr,
- unsigned long len,
- unsigned long pgoff,
- unsigned long flags)
-{
- struct vm_area_struct *vma;
- direct_mmap_node_t * node;
- struct list_head * curr;
- struct list_head * direct_list = ¤t->mm->context.direct_list;
-
- if ( len > TASK_SIZE )
- return -ENOMEM;
-
- if ( addr )
- {
- addr = PAGE_ALIGN(addr);
- vma = find_vma(current->mm, addr);
- curr = find_direct(direct_list, addr);
- node = list_entry(curr, direct_mmap_node_t, list);
- if ( (TASK_SIZE - len >= addr) &&
- (!vma || addr + len <= vma->vm_start) &&
- ((curr == direct_list) || addr + len <= node->vm_start) )
- return addr;
- }
-
- addr = PAGE_ALIGN(TASK_UNMAPPED_BASE);
-
-
- /* Find first VMA and direct_map nodes with vm_start > addr */
- vma = find_vma(current->mm, addr);
- curr = find_direct(direct_list, addr);
- node = list_entry(curr, direct_mmap_node_t, list);
-
- for ( ; ; )
- {
- if ( TASK_SIZE - len < addr ) return -ENOMEM;
-
- if ( vma && ((curr == direct_list) ||
- (vma->vm_start < node->vm_start)) )
- {
- /* Do we fit before VMA node? */
- if ( addr + len <= vma->vm_start ) return addr;
- addr = vma->vm_end;
- vma = vma->vm_next;
- }
- else if ( curr != direct_list )
- {
- /* Do we fit before direct_map node? */
- if ( addr + len <= node->vm_start) return addr;
- addr = node->vm_end;
- curr = curr->next;
- node = list_entry(curr, direct_mmap_node_t, list);
- }
- else
- {
- /* !vma && curr == direct_list */
- return addr;
- }
- }
-}
#include <asm/tlb.h>
#include <asm/mmu.h>
+#if defined(CONFIG_XENO_PRIV)
+
#define direct_set_pte(pteptr, pteval) \
queue_l1_entry_update(__pa(pteptr)|PGREQ_UNCHECKED_UPDATE, (pteval).pte_low)
-#define direct_pte_clear(pteptr) \
- queue_l1_entry_update(__pa(pteptr)|PGREQ_UNCHECKED_UPDATE, 0)
#define __direct_pte(x) ((pte_t) { (x) } )
#define __direct_mk_pte(page_nr,pgprot) \
__direct_pte(((page_nr) << PAGE_SHIFT) | pgprot_val(pgprot))
__direct_mk_pte((physpage) >> PAGE_SHIFT, pgprot)
-
-/******************* Mapping a page range directly ************************/
-
static inline void direct_remap_area_pte(pte_t *pte,
unsigned long address,
unsigned long size,
printk("direct_remap_area_pte: page already exists\n");
BUG();
}
- direct_set_pte(pte, direct_mk_pte_phys(machine_addr, prot));
+ direct_set_pte(pte, pte_mkio(direct_mk_pte_phys(machine_addr, prot)));
address += PAGE_SIZE;
machine_addr += PAGE_SIZE;
pte++;
return error;
}
+#endif /* CONFIG_XENO_PRIV */
-/************************ Zapping a page range directly *******************/
-
-static inline int direct_zap_pte_range(mmu_gather_t *tlb,
- pmd_t * pmd,
- unsigned long address,
- unsigned long size)
-{
- unsigned long offset;
- pte_t * ptep;
- int freed = 0;
-
- if (pmd_none(*pmd))
- return 0;
- if (pmd_bad(*pmd)) {
- pmd_ERROR(*pmd);
- pmd_clear(pmd);
- return 0;
- }
- ptep = pte_offset(pmd, address);
- offset = address & ~PMD_MASK;
- if (offset + size > PMD_SIZE)
- size = PMD_SIZE - offset;
- size &= PAGE_MASK;
- for (offset=0; offset < size; ptep++, offset += PAGE_SIZE) {
- pte_t pte = *ptep;
- if (pte_none(pte))
- continue;
- freed++;
- direct_pte_clear(ptep);
- }
-
- return freed;
-}
-
-static inline int direct_zap_pmd_range(mmu_gather_t *tlb,
- pgd_t * dir,
- unsigned long address,
- unsigned long size)
-{
- pmd_t * pmd;
- unsigned long end;
- int freed;
-
- if (pgd_none(*dir))
- return 0;
- if (pgd_bad(*dir)) {
- pgd_ERROR(*dir);
- pgd_clear(dir);
- return 0;
- }
- pmd = pmd_offset(dir, address);
- end = address + size;
- if (end > ((address + PGDIR_SIZE) & PGDIR_MASK))
- end = ((address + PGDIR_SIZE) & PGDIR_MASK);
- freed = 0;
- do {
- freed += direct_zap_pte_range(tlb, pmd, address, end - address);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address < end);
- return freed;
-}
-
-void direct_zap_page_range(struct mm_struct *mm,
- unsigned long address,
- unsigned long size)
-{
- mmu_gather_t *tlb;
- pgd_t * dir;
- unsigned long start = address, end = address + size;
- int freed = 0;
-
- dir = pgd_offset(mm, address);
-
- if (address >= end)
- BUG();
- spin_lock(&mm->page_table_lock);
- flush_cache_range(mm, address, end);
- tlb = tlb_gather_mmu(mm);
-
- do {
- freed += direct_zap_pmd_range(tlb, dir, address, end - address);
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
-
- /* this will flush any remaining tlb entries */
- tlb_finish_mmu(tlb, start, end);
-
- /* decrementing rss removed */
- spin_unlock(&mm->page_table_lock);
-}
-
-
-
-/****************** Generic public functions ****************************/
-
/*
* Remap an arbitrary machine address space into the kernel virtual
* address space. Needed when a privileged instance of Xenolinux wants
unsigned long size,
unsigned long flags)
{
+#if defined(CONFIG_XENO_PRIV)
void * addr;
struct vm_struct * area;
unsigned long offset, last_addr;
if (!area)
return NULL;
addr = area->addr;
- prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED |
- flags);
+ prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY |
+ _PAGE_ACCESSED | flags);
if (direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(addr),
machine_addr, size, prot)) {
vfree(addr);
return NULL;
}
return (void *) (offset + (char *)addr);
+#else
+ return NULL;
+#endif
}
-/*
- * 'vfree' is basically inlined here. This is because we use a different
- * function to zap the associated page range.
- */
void iounmap(void *addr)
{
- struct vm_struct **p, *tmp;
-
- addr = (void *)((unsigned long)addr & PAGE_MASK);
-
- if (addr == NULL)
- return;
-
- write_lock(&vmlist_lock);
-
- for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
- if (tmp->addr == addr) {
- *p = tmp->next;
- direct_zap_page_range(&init_mm,
- VMALLOC_VMADDR(tmp->addr),
- tmp->size);
- write_unlock(&vmlist_lock);
- kfree(tmp);
- return;
- }
- }
-
- write_unlock(&vmlist_lock);
- printk(KERN_ERR "Trying to iounmap() nonexistent vm area (%p)\n", addr);
+ vfree((void *)((unsigned long)addr & PAGE_MASK));
}
--- /dev/null
+/*
+ * linux/drivers/char/mem.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * Added devfs support.
+ * Jan-11-1998, C. Scott Ananian <cananian@alumni.princeton.edu>
+ * Shared /dev/zero mmaping support, Feb 2000, Kanoj Sarcar <kanoj@sgi.com>
+ *
+ * MODIFIED FOR XENOLINUX by Keir Fraser, 10th July 2003.
+ * Xenolinux has strange semantics for /dev/mem and /dev/kmem!!
+ * 1. mmap will not work on /dev/kmem
+ * 2. mmap on /dev/mem interprets the 'file offset' as a machine address
+ * rather than a physical address.
+ * I don't believe anyone sane mmaps /dev/kmem, but /dev/mem is mmapped
+ * to get at memory-mapped I/O spaces (eg. the VESA X server does this).
+ * For this to work at all we need to expect machine addresses.
+ * Reading/writing of /dev/kmem expects kernel virtual addresses, as usual.
+ * Reading/writing of /dev/mem expects 'physical addresses' as usual -- this
+ * is because /dev/mem can only read/write existing kernel mappings, which
+ * will be normal RAM, and we should present pseudo-physical layout for all
+ * except I/O (which is the sticky case that mmap is hacked to deal with).
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/tpqic02.h>
+#include <linux/ftape.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/mman.h>
+#include <linux/random.h>
+#include <linux/init.h>
+#include <linux/raw.h>
+#include <linux/tty.h>
+#include <linux/capability.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+
+#ifdef CONFIG_I2C
+extern int i2c_init_all(void);
+#endif
+#ifdef CONFIG_FB
+extern void fbmem_init(void);
+#endif
+#ifdef CONFIG_PROM_CONSOLE
+extern void prom_con_init(void);
+#endif
+#ifdef CONFIG_MDA_CONSOLE
+extern void mda_console_init(void);
+#endif
+#if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR)
+extern void tapechar_init(void);
+#endif
+
+static ssize_t do_write_mem(struct file * file, void *p, unsigned long realp,
+ const char * buf, size_t count, loff_t *ppos)
+{
+ ssize_t written;
+
+ written = 0;
+#if defined(__sparc__) || defined(__mc68000__)
+ /* we don't have page 0 mapped on sparc and m68k.. */
+ if (realp < PAGE_SIZE) {
+ unsigned long sz = PAGE_SIZE-realp;
+ if (sz > count) sz = count;
+ /* Hmm. Do something? */
+ buf+=sz;
+ p+=sz;
+ count-=sz;
+ written+=sz;
+ }
+#endif
+ if (copy_from_user(p, buf, count))
+ return -EFAULT;
+ written += count;
+ *ppos += written;
+ return written;
+}
+
+
+/*
+ * This funcion reads the *physical* memory. The f_pos points directly to the
+ * memory location.
+ */
+static ssize_t read_mem(struct file * file, char * buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long p = *ppos;
+ unsigned long end_mem;
+ ssize_t read;
+
+ end_mem = __pa(high_memory);
+ if (p >= end_mem)
+ return 0;
+ if (count > end_mem - p)
+ count = end_mem - p;
+ read = 0;
+#if defined(__sparc__) || defined(__mc68000__)
+ /* we don't have page 0 mapped on sparc and m68k.. */
+ if (p < PAGE_SIZE) {
+ unsigned long sz = PAGE_SIZE-p;
+ if (sz > count)
+ sz = count;
+ if (sz > 0) {
+ if (clear_user(buf, sz))
+ return -EFAULT;
+ buf += sz;
+ p += sz;
+ count -= sz;
+ read += sz;
+ }
+ }
+#endif
+ if (copy_to_user(buf, __va(p), count))
+ return -EFAULT;
+ read += count;
+ *ppos += read;
+ return read;
+}
+
+static ssize_t write_mem(struct file * file, const char * buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long p = *ppos;
+ unsigned long end_mem;
+
+ end_mem = __pa(high_memory);
+ if (p >= end_mem)
+ return 0;
+ if (count > end_mem - p)
+ count = end_mem - p;
+ return do_write_mem(file, __va(p), p, buf, count, ppos);
+}
+
+#ifndef pgprot_noncached
+
+/*
+ * This should probably be per-architecture in <asm/pgtable.h>
+ */
+static inline pgprot_t pgprot_noncached(pgprot_t _prot)
+{
+ unsigned long prot = pgprot_val(_prot);
+
+#if defined(__i386__) || defined(__x86_64__)
+ /* On PPro and successors, PCD alone doesn't always mean
+ uncached because of interactions with the MTRRs. PCD | PWT
+ means definitely uncached. */
+ if (boot_cpu_data.x86 > 3)
+ prot |= _PAGE_PCD | _PAGE_PWT;
+#elif defined(__powerpc__)
+ prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
+#elif defined(__mc68000__)
+#ifdef SUN3_PAGE_NOCACHE
+ if (MMU_IS_SUN3)
+ prot |= SUN3_PAGE_NOCACHE;
+ else
+#endif
+ if (MMU_IS_851 || MMU_IS_030)
+ prot |= _PAGE_NOCACHE030;
+ /* Use no-cache mode, serialized */
+ else if (MMU_IS_040 || MMU_IS_060)
+ prot = (prot & _CACHEMASK040) | _PAGE_NOCACHE_S;
+#endif
+
+ return __pgprot(prot);
+}
+
+#endif /* !pgprot_noncached */
+
+/*
+ * Architectures vary in how they handle caching for addresses
+ * outside of main memory.
+ */
+static inline int noncached_address(unsigned long addr)
+{
+#if defined(__i386__)
+ /*
+ * On the PPro and successors, the MTRRs are used to set
+ * memory types for physical addresses outside main memory,
+ * so blindly setting PCD or PWT on those pages is wrong.
+ * For Pentiums and earlier, the surround logic should disable
+ * caching for the high addresses through the KEN pin, but
+ * we maintain the tradition of paranoia in this code.
+ */
+ return !( test_bit(X86_FEATURE_MTRR, &boot_cpu_data.x86_capability) ||
+ test_bit(X86_FEATURE_K6_MTRR, &boot_cpu_data.x86_capability) ||
+ test_bit(X86_FEATURE_CYRIX_ARR, &boot_cpu_data.x86_capability) ||
+ test_bit(X86_FEATURE_CENTAUR_MCR, &boot_cpu_data.x86_capability) )
+ && addr >= __pa(high_memory);
+#else
+ return addr >= __pa(high_memory);
+#endif
+}
+
+static int mmap_mem(struct file * file, struct vm_area_struct * vma)
+{
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+
+#if defined(CONFIG_XENO) && defined(CONFIG_XENO_PRIV)
+ if (!(start_info.flags & SIF_PRIVILEGED))
+ return -ENXIO;
+
+ /* DONTCOPY is essential for Xenolinux as copy_page_range is broken. */
+ vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ if (direct_remap_area_pages(vma->vm_mm, vma->vm_start, offset,
+ vma->vm_end-vma->vm_start, vma->vm_page_prot))
+ return -EAGAIN;
+ return 0;
+#elif defined(CONFIG_XENO)
+ return -ENXIO;
+#else
+ /*
+ * Accessing memory above the top the kernel knows about or
+ * through a file pointer that was marked O_SYNC will be
+ * done non-cached.
+ */
+ if (noncached_address(offset) || (file->f_flags & O_SYNC))
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ /* Don't try to swap out physical pages.. */
+ vma->vm_flags |= VM_RESERVED;
+
+ /*
+ * Don't dump addresses that are not real memory to a core file.
+ */
+ if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC))
+ vma->vm_flags |= VM_IO;
+
+ if (remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start,
+ vma->vm_page_prot))
+ return -EAGAIN;
+ return 0;
+#endif
+}
+
+/*
+ * This function reads the *virtual* memory as seen by the kernel.
+ */
+static ssize_t read_kmem(struct file *file, char *buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long p = *ppos;
+ ssize_t read = 0;
+ ssize_t virtr = 0;
+ char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
+
+ if (p < (unsigned long) high_memory) {
+ read = count;
+ if (count > (unsigned long) high_memory - p)
+ read = (unsigned long) high_memory - p;
+
+#if defined(__sparc__) || defined(__mc68000__)
+ /* we don't have page 0 mapped on sparc and m68k.. */
+ if (p < PAGE_SIZE && read > 0) {
+ size_t tmp = PAGE_SIZE - p;
+ if (tmp > read) tmp = read;
+ if (clear_user(buf, tmp))
+ return -EFAULT;
+ buf += tmp;
+ p += tmp;
+ read -= tmp;
+ count -= tmp;
+ }
+#endif
+ if (copy_to_user(buf, (char *)p, read))
+ return -EFAULT;
+ p += read;
+ buf += read;
+ count -= read;
+ }
+
+ if (count > 0) {
+ kbuf = (char *)__get_free_page(GFP_KERNEL);
+ if (!kbuf)
+ return -ENOMEM;
+ while (count > 0) {
+ int len = count;
+
+ if (len > PAGE_SIZE)
+ len = PAGE_SIZE;
+ len = vread(kbuf, (char *)p, len);
+ if (!len)
+ break;
+ if (copy_to_user(buf, kbuf, len)) {
+ free_page((unsigned long)kbuf);
+ return -EFAULT;
+ }
+ count -= len;
+ buf += len;
+ virtr += len;
+ p += len;
+ }
+ free_page((unsigned long)kbuf);
+ }
+ *ppos = p;
+ return virtr + read;
+}
+
+extern long vwrite(char *buf, char *addr, unsigned long count);
+
+/*
+ * This function writes to the *virtual* memory as seen by the kernel.
+ */
+static ssize_t write_kmem(struct file * file, const char * buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long p = *ppos;
+ ssize_t wrote = 0;
+ ssize_t virtr = 0;
+ char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
+
+ if (p < (unsigned long) high_memory) {
+ wrote = count;
+ if (count > (unsigned long) high_memory - p)
+ wrote = (unsigned long) high_memory - p;
+
+ wrote = do_write_mem(file, (void*)p, p, buf, wrote, ppos);
+
+ p += wrote;
+ buf += wrote;
+ count -= wrote;
+ }
+
+ if (count > 0) {
+ kbuf = (char *)__get_free_page(GFP_KERNEL);
+ if (!kbuf)
+ return -ENOMEM;
+ while (count > 0) {
+ int len = count;
+
+ if (len > PAGE_SIZE)
+ len = PAGE_SIZE;
+ if (len && copy_from_user(kbuf, buf, len)) {
+ free_page((unsigned long)kbuf);
+ return -EFAULT;
+ }
+ len = vwrite(kbuf, (char *)p, len);
+ count -= len;
+ buf += len;
+ virtr += len;
+ p += len;
+ }
+ free_page((unsigned long)kbuf);
+ }
+
+ *ppos = p;
+ return virtr + wrote;
+}
+
+#if defined(CONFIG_ISA) || !defined(__mc68000__)
+static ssize_t read_port(struct file * file, char * buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long i = *ppos;
+ char *tmp = buf;
+
+ if (verify_area(VERIFY_WRITE,buf,count))
+ return -EFAULT;
+ while (count-- > 0 && i < 65536) {
+ if (__put_user(inb(i),tmp) < 0)
+ return -EFAULT;
+ i++;
+ tmp++;
+ }
+ *ppos = i;
+ return tmp-buf;
+}
+
+static ssize_t write_port(struct file * file, const char * buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long i = *ppos;
+ const char * tmp = buf;
+
+ if (verify_area(VERIFY_READ,buf,count))
+ return -EFAULT;
+ while (count-- > 0 && i < 65536) {
+ char c;
+ if (__get_user(c, tmp))
+ return -EFAULT;
+ outb(c,i);
+ i++;
+ tmp++;
+ }
+ *ppos = i;
+ return tmp-buf;
+}
+#endif
+
+static ssize_t read_null(struct file * file, char * buf,
+ size_t count, loff_t *ppos)
+{
+ return 0;
+}
+
+static ssize_t write_null(struct file * file, const char * buf,
+ size_t count, loff_t *ppos)
+{
+ return count;
+}
+
+/*
+ * For fun, we are using the MMU for this.
+ */
+static inline size_t read_zero_pagealigned(char * buf, size_t size)
+{
+ struct mm_struct *mm;
+ struct vm_area_struct * vma;
+ unsigned long addr=(unsigned long)buf;
+
+ mm = current->mm;
+ /* Oops, this was forgotten before. -ben */
+ down_read(&mm->mmap_sem);
+
+ /* For private mappings, just map in zero pages. */
+ for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) {
+ unsigned long count;
+
+ if (vma->vm_start > addr || (vma->vm_flags & VM_WRITE) == 0)
+ goto out_up;
+ if (vma->vm_flags & VM_SHARED)
+ break;
+#if defined(CONFIG_XENO_PRIV)
+ if (vma->vm_flags & VM_IO)
+ break;
+#endif
+ count = vma->vm_end - addr;
+ if (count > size)
+ count = size;
+
+ zap_page_range(mm, addr, count);
+ zeromap_page_range(addr, count, PAGE_COPY);
+
+ size -= count;
+ buf += count;
+ addr += count;
+ if (size == 0)
+ goto out_up;
+ }
+
+ up_read(&mm->mmap_sem);
+
+ /* The shared case is hard. Let's do the conventional zeroing. */
+ do {
+ unsigned long unwritten = clear_user(buf, PAGE_SIZE);
+ if (unwritten)
+ return size + unwritten - PAGE_SIZE;
+ if (current->need_resched)
+ schedule();
+ buf += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ } while (size);
+
+ return size;
+out_up:
+ up_read(&mm->mmap_sem);
+ return size;
+}
+
+static ssize_t read_zero(struct file * file, char * buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long left, unwritten, written = 0;
+
+ if (!count)
+ return 0;
+
+ if (!access_ok(VERIFY_WRITE, buf, count))
+ return -EFAULT;
+
+ left = count;
+
+ /* do we want to be clever? Arbitrary cut-off */
+ if (count >= PAGE_SIZE*4) {
+ unsigned long partial;
+
+ /* How much left of the page? */
+ partial = (PAGE_SIZE-1) & -(unsigned long) buf;
+ unwritten = clear_user(buf, partial);
+ written = partial - unwritten;
+ if (unwritten)
+ goto out;
+ left -= partial;
+ buf += partial;
+ unwritten = read_zero_pagealigned(buf, left & PAGE_MASK);
+ written += (left & PAGE_MASK) - unwritten;
+ if (unwritten)
+ goto out;
+ buf += left & PAGE_MASK;
+ left &= ~PAGE_MASK;
+ }
+ unwritten = clear_user(buf, left);
+ written += left - unwritten;
+out:
+ return written ? written : -EFAULT;
+}
+
+static int mmap_zero(struct file * file, struct vm_area_struct * vma)
+{
+ if (vma->vm_flags & VM_SHARED)
+ return shmem_zero_setup(vma);
+ if (zeromap_page_range(vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot))
+ return -EAGAIN;
+ return 0;
+}
+
+static ssize_t write_full(struct file * file, const char * buf,
+ size_t count, loff_t *ppos)
+{
+ return -ENOSPC;
+}
+
+/*
+ * Special lseek() function for /dev/null and /dev/zero. Most notably, you
+ * can fopen() both devices with "a" now. This was previously impossible.
+ * -- SRB.
+ */
+
+static loff_t null_lseek(struct file * file, loff_t offset, int orig)
+{
+ return file->f_pos = 0;
+}
+
+/*
+ * The memory devices use the full 32/64 bits of the offset, and so we cannot
+ * check against negative addresses: they are ok. The return value is weird,
+ * though, in that case (0).
+ *
+ * also note that seeking relative to the "end of file" isn't supported:
+ * it has no meaning, so it returns -EINVAL.
+ */
+static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
+{
+ switch (orig) {
+ case 0:
+ file->f_pos = offset;
+ return file->f_pos;
+ case 1:
+ file->f_pos += offset;
+ return file->f_pos;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int open_port(struct inode * inode, struct file * filp)
+{
+ return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
+}
+
+struct page *kmem_vm_nopage(struct vm_area_struct *vma, unsigned long address, int write)
+{
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ unsigned long kaddr;
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *ptep, pte;
+ struct page *page = NULL;
+
+ /* address is user VA; convert to kernel VA of desired page */
+ kaddr = (address - vma->vm_start) + offset;
+ kaddr = VMALLOC_VMADDR(kaddr);
+
+ spin_lock(&init_mm.page_table_lock);
+
+ /* Lookup page structure for kernel VA */
+ pgd = pgd_offset(&init_mm, kaddr);
+ if (pgd_none(*pgd) || pgd_bad(*pgd))
+ goto out;
+ pmd = pmd_offset(pgd, kaddr);
+ if (pmd_none(*pmd) || pmd_bad(*pmd))
+ goto out;
+ ptep = pte_offset(pmd, kaddr);
+ if (!ptep)
+ goto out;
+ pte = *ptep;
+ if (!pte_present(pte))
+ goto out;
+ if (write && !pte_write(pte))
+ goto out;
+ page = pte_page(pte);
+ if (!VALID_PAGE(page)) {
+ page = NULL;
+ goto out;
+ }
+
+ /* Increment reference count on page */
+ get_page(page);
+
+out:
+ spin_unlock(&init_mm.page_table_lock);
+
+ return page;
+}
+
+struct vm_operations_struct kmem_vm_ops = {
+ nopage: kmem_vm_nopage,
+};
+
+static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
+{
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ unsigned long size = vma->vm_end - vma->vm_start;
+
+#if defined(CONFIG_XENO)
+ return -ENXIO;
+#endif
+
+ /*
+ * If the user is not attempting to mmap a high memory address then
+ * the standard mmap_mem mechanism will work. High memory addresses
+ * need special handling, as remap_page_range expects a physically-
+ * contiguous range of kernel addresses (such as obtained in kmalloc).
+ */
+ if ((offset + size) < (unsigned long) high_memory)
+ return mmap_mem(file, vma);
+
+ /*
+ * Accessing memory above the top the kernel knows about or
+ * through a file pointer that was marked O_SYNC will be
+ * done non-cached.
+ */
+ if (noncached_address(offset) || (file->f_flags & O_SYNC))
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ /* Don't do anything here; "nopage" will fill the holes */
+ vma->vm_ops = &kmem_vm_ops;
+
+ /* Don't try to swap out physical pages.. */
+ vma->vm_flags |= VM_RESERVED;
+
+ /*
+ * Don't dump addresses that are not real memory to a core file.
+ */
+ vma->vm_flags |= VM_IO;
+
+ return 0;
+}
+
+#define zero_lseek null_lseek
+#define full_lseek null_lseek
+#define write_zero write_null
+#define read_full read_zero
+#define open_mem open_port
+#define open_kmem open_mem
+
+static struct file_operations mem_fops = {
+ llseek: memory_lseek,
+ read: read_mem,
+ write: write_mem,
+ mmap: mmap_mem,
+ open: open_mem,
+};
+
+static struct file_operations kmem_fops = {
+ llseek: memory_lseek,
+ read: read_kmem,
+ write: write_kmem,
+ mmap: mmap_kmem,
+ open: open_kmem,
+};
+
+static struct file_operations null_fops = {
+ llseek: null_lseek,
+ read: read_null,
+ write: write_null,
+};
+
+#if defined(CONFIG_ISA) || !defined(__mc68000__)
+static struct file_operations port_fops = {
+ llseek: memory_lseek,
+ read: read_port,
+ write: write_port,
+ open: open_port,
+};
+#endif
+
+static struct file_operations zero_fops = {
+ llseek: zero_lseek,
+ read: read_zero,
+ write: write_zero,
+ mmap: mmap_zero,
+};
+
+static struct file_operations full_fops = {
+ llseek: full_lseek,
+ read: read_full,
+ write: write_full,
+};
+
+static int memory_open(struct inode * inode, struct file * filp)
+{
+ switch (MINOR(inode->i_rdev)) {
+ case 1:
+ filp->f_op = &mem_fops;
+ break;
+ case 2:
+ filp->f_op = &kmem_fops;
+ break;
+ case 3:
+ filp->f_op = &null_fops;
+ break;
+#if defined(CONFIG_ISA) || !defined(__mc68000__)
+ case 4:
+#if defined(CONFIG_XENO)
+#if defined(CONFIG_XENO_PRIV)
+ if (!(start_info.flags & SIF_PRIVILEGED))
+#endif
+ return -ENXIO;
+#endif
+ filp->f_op = &port_fops;
+ break;
+#endif
+ case 5:
+ filp->f_op = &zero_fops;
+ break;
+ case 7:
+ filp->f_op = &full_fops;
+ break;
+ case 8:
+ filp->f_op = &random_fops;
+ break;
+ case 9:
+ filp->f_op = &urandom_fops;
+ break;
+ default:
+ return -ENXIO;
+ }
+ if (filp->f_op && filp->f_op->open)
+ return filp->f_op->open(inode,filp);
+ return 0;
+}
+
+void __init memory_devfs_register (void)
+{
+ /* These are never unregistered */
+ static const struct {
+ unsigned short minor;
+ char *name;
+ umode_t mode;
+ struct file_operations *fops;
+ } list[] = { /* list of minor devices */
+ {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
+ {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
+ {3, "null", S_IRUGO | S_IWUGO, &null_fops},
+#if defined(CONFIG_ISA) || !defined(__mc68000__)
+ {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
+#endif
+ {5, "zero", S_IRUGO | S_IWUGO, &zero_fops},
+ {7, "full", S_IRUGO | S_IWUGO, &full_fops},
+ {8, "random", S_IRUGO | S_IWUSR, &random_fops},
+ {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops}
+ };
+ int i;
+
+ for (i=0; i<(sizeof(list)/sizeof(*list)); i++)
+ devfs_register (NULL, list[i].name, DEVFS_FL_NONE,
+ MEM_MAJOR, list[i].minor,
+ list[i].mode | S_IFCHR,
+ list[i].fops, NULL);
+}
+
+static struct file_operations memory_fops = {
+ open: memory_open, /* just a selector for the real open */
+};
+
+int __init chr_dev_init(void)
+{
+ if (devfs_register_chrdev(MEM_MAJOR,"mem",&memory_fops))
+ printk("unable to get major %d for memory devs\n", MEM_MAJOR);
+ memory_devfs_register();
+ rand_initialize();
+#ifdef CONFIG_I2C
+ i2c_init_all();
+#endif
+#if defined (CONFIG_FB)
+ fbmem_init();
+#endif
+#if defined (CONFIG_PROM_CONSOLE)
+ prom_con_init();
+#endif
+#if defined (CONFIG_MDA_CONSOLE)
+ mda_console_init();
+#endif
+ tty_init();
+#ifdef CONFIG_M68K_PRINTER
+ lp_m68k_init();
+#endif
+ misc_init();
+#if CONFIG_QIC02_TAPE
+ qic02_tape_init();
+#endif
+#ifdef CONFIG_FTAPE
+ ftape_init();
+#endif
+#if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR)
+ tapechar_init();
+#endif
+ return 0;
+}
+
+__initcall(chr_dev_init);
+++ /dev/null
-/* IOCTLs used when access /proc/xeno/dom0_cmd. */
-#ifndef __DOM0_H__
-#define __DOM0_H__
-
-#define IOCTL_DOM0_CREATEDOMAIN _IOC(_IOC_READ, 'x', 0, sizeof(struct dom0_createdomain_args))
-#define IOCTL_DOM0_MAPDOMMEM _IOC(_IOC_READ, 'x', 1, sizeof(struct dom0_mapdommem_args))
-#define IOCTL_DOM0_UNMAPDOMMEM _IOC(_IOC_READ, 'x', 2, sizeof(struct dom0_unmapdommem_args))
-#define IOCTL_DOM0_DOPGUPDATES _IOC(_IOC_READ, 'x', 3, sizeof(struct dom0_dopgupdates_args))
-
-struct dom0_createdomain_args
-{
- unsigned int kb_mem;
- const char *name;
-};
-
-struct dom0_mapdommem_args
-{
- unsigned int domain;
- unsigned start_pfn;
- unsigned tot_pages;
-};
-
-struct dom0_unmapdommem_args
-{
- unsigned long vaddr;
- unsigned long start_pfn;
- unsigned long tot_pages;
-};
-
-struct dom0_dopgupdates_args
-{
- unsigned long pgt_update_arr;
- unsigned long num_pgt_updates;
-};
-
-#endif /* __DOM0_H__ */
#ifndef __HYPERVISOR_H__
#define __HYPERVISOR_H__
+#include <linux/types.h>
#include <asm/hypervisor-ifs/hypervisor-if.h>
#include <asm/ptrace.h>
-//#include <asm/page.h>
/* arch/xeno/kernel/setup.c */
union start_info_union
+++ /dev/null
-#ifndef __i386_MMU_H
-#define __i386_MMU_H
-
-#include <linux/list.h>
-
-/* describes dirrectly mapped vma nodes */
-typedef struct {
- struct list_head list;
- unsigned long vm_start;
- unsigned long vm_end;
-} direct_mmap_node_t;
-
-/*
- * The i386 doesn't have a mmu context, but
- * we put the segment information here.
- */
-typedef struct {
- void *segments;
- unsigned long cpuvalid;
- struct list_head direct_list;
-} mm_context_t;
-
-#endif
#include <asm/desc.h>
#include <asm/atomic.h>
#include <asm/pgalloc.h>
-#include <asm/multicall.h>
-
-/* Hooked directly from 'init_new_context'. */
-extern int init_direct_list(struct mm_struct *);
-/* Called from 'release_segments'. */
-extern void destroy_direct_list(struct mm_struct *);
+/*
+ * possibly do the LDT unload here?
+ */
#define destroy_context(mm) do { } while(0)
-#define init_new_context(tsk,mm) init_direct_list(mm)
+#define init_new_context(tsk,mm) 0
#ifdef CONFIG_SMP
nr_multicall_ents = i+1;
}
+static inline void queue_multicall3(
+ unsigned long op, unsigned long arg1, unsigned long arg2,
+ unsigned long arg3)
+{
+ int i = nr_multicall_ents;
+ multicall_list[i].op = op;
+ multicall_list[i].args[0] = arg1;
+ multicall_list[i].args[1] = arg2;
+ multicall_list[i].args[2] = arg3;
+ nr_multicall_ents = i+1;
+}
+
+static inline void queue_multicall4(
+ unsigned long op, unsigned long arg1, unsigned long arg2,
+ unsigned long arg3, unsigned long arg4)
+{
+ int i = nr_multicall_ents;
+ multicall_list[i].op = op;
+ multicall_list[i].args[0] = arg1;
+ multicall_list[i].args[1] = arg2;
+ multicall_list[i].args[2] = arg3;
+ multicall_list[i].args[3] = arg4;
+ nr_multicall_ents = i+1;
+}
+
+static inline void queue_multicall5(
+ unsigned long op, unsigned long arg1, unsigned long arg2,
+ unsigned long arg3, unsigned long arg4, unsigned long arg5)
+{
+ int i = nr_multicall_ents;
+ multicall_list[i].op = op;
+ multicall_list[i].args[0] = arg1;
+ multicall_list[i].args[1] = arg2;
+ multicall_list[i].args[2] = arg3;
+ multicall_list[i].args[3] = arg4;
+ multicall_list[i].args[4] = arg5;
+ nr_multicall_ents = i+1;
+}
+
static inline void execute_multicall_list(void)
{
if ( unlikely(nr_multicall_ents == 0) ) return;
XENO_flush_page_update_queue();
}
+extern int direct_remap_area_pages(struct mm_struct *mm,
+ unsigned long address,
+ unsigned long machine_addr,
+ unsigned long size,
+ pgprot_t prot);
+
#endif /* _I386_PGALLOC_H */
#include <linux/config.h>
-#define HAVE_ARCH_UNMAPPED_AREA
-
/*
* The Linux memory management assumes a three-level page table setup. On
* the i386, we use that, but "fold" the mid level into the top-level page
#define _PAGE_BIT_DIRTY 6
#define _PAGE_BIT_PSE 7 /* 4 MB (or 2MB) page, Pentium+, if present.. */
#define _PAGE_BIT_GLOBAL 8 /* Global TLB entry PPro+ */
+#define _PAGE_BIT_IO 9
#define _PAGE_PRESENT 0x001
#define _PAGE_RW 0x002
#define _PAGE_DIRTY 0x040
#define _PAGE_PSE 0x080 /* 4 MB (or 2MB) page, Pentium+, if present.. */
#define _PAGE_GLOBAL 0x100 /* Global TLB entry PPro+ */
+#define _PAGE_IO 0x200
#define _PAGE_PROTNONE 0x080 /* If not present */
static inline int pte_dirty(pte_t pte) { return (pte).pte_low & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return (pte).pte_low & _PAGE_ACCESSED; }
static inline int pte_write(pte_t pte) { return (pte).pte_low & _PAGE_RW; }
+static inline int pte_io(pte_t pte) { return (pte).pte_low & _PAGE_IO; }
static inline pte_t pte_rdprotect(pte_t pte) { (pte).pte_low &= ~_PAGE_USER; return pte; }
static inline pte_t pte_exprotect(pte_t pte) { (pte).pte_low &= ~_PAGE_USER; return pte; }
static inline pte_t pte_mkdirty(pte_t pte) { (pte).pte_low |= _PAGE_DIRTY; return pte; }
static inline pte_t pte_mkyoung(pte_t pte) { (pte).pte_low |= _PAGE_ACCESSED; return pte; }
static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte_low |= _PAGE_RW; return pte; }
+static inline pte_t pte_mkio(pte_t pte) { (pte).pte_low |= _PAGE_IO; return pte; }
static inline int ptep_test_and_clear_dirty(pte_t *ptep)
{
--- /dev/null
+/******************************************************************************
+ * proc_cmd.h
+ *
+ * Interface to /proc/cmd and /proc/xeno/privcmd.
+ */
+
+#ifndef __PROC_CMD_H__
+#define __PROC_CMD_H__
+
+#define IOCTL_PRIVCMD_HYPERCALL 0
+#define IOCTL_PRIVCMD_BLKMSG 1
+#define IOCTL_PRIVCMD_LINDEV_TO_XENDEV 2
+#define IOCTL_PRIVCMD_XENDEV_TO_LINDEV 3
+
+typedef struct privcmd_hypercall
+{
+ unsigned long op;
+ unsigned long arg[5];
+} privcmd_hypercall_t;
+
+typedef struct privcmd_blkmsg
+{
+ unsigned long op;
+ void *buf;
+ int buf_size;
+} privcmd_blkmsg_t;
+
+#endif /* __PROC_CMD_H__ */
#ifndef _ASM_SEGMENT_H
#define _ASM_SEGMENT_H
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+#endif
#include <asm/hypervisor-ifs/hypervisor-if.h>
#define __KERNEL_CS FLAT_RING1_CS
ln -sf ../asm-i386/mc146818rtc.h
ln -sf ../asm-i386/mca_dma.h
ln -sf ../asm-i386/mman.h
+ln -sf ../asm-i386/mmu.h
ln -sf ../asm-i386/mmx.h
ln -sf ../asm-i386/module.h
ln -sf ../asm-i386/mpspec.h
continue;
if (pte_present(pte)) {
struct page *page = pte_page(pte);
+#if defined(CONFIG_XENO_PRIV)
+ if (pte_io(pte)) {
+ queue_l1_entry_update(
+ __pa(ptep)|PGREQ_UNCHECKED_UPDATE, 0);
+ continue;
+ }
+#endif
if (VALID_PAGE(page) && !PageReserved(page))
freed ++;
/* This will eventually call __free_pte on the pte. */
pgd_t *pgd;
pmd_t *pmd;
+#if defined(CONFIG_XENO_PRIV)
+ /* Take care of I/O mappings right here. */
+ if (vma->vm_flags & VM_IO) {
+ if (write_access && !(vma->vm_flags & VM_WRITE))
+ return -1;
+ return 1;
+ }
+#endif
+
current->state = TASK_RUNNING;
pgd = pgd_offset(mm, address);
--- /dev/null
+/*
+ * linux/mm/mprotect.c
+ *
+ * (C) Copyright 1994 Linus Torvalds
+ */
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/shm.h>
+#include <linux/mman.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+
+static inline void change_pte_range(pmd_t * pmd, unsigned long address,
+ unsigned long size, pgprot_t newprot)
+{
+ pte_t * pte;
+ unsigned long end;
+
+ if (pmd_none(*pmd))
+ return;
+ if (pmd_bad(*pmd)) {
+ pmd_ERROR(*pmd);
+ pmd_clear(pmd);
+ return;
+ }
+ pte = pte_offset(pmd, address);
+ address &= ~PMD_MASK;
+ end = address + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ do {
+ if (pte_present(*pte)) {
+ pte_t entry;
+
+ /* Avoid an SMP race with hardware updated dirty/clean
+ * bits by wiping the pte and then setting the new pte
+ * into place.
+ */
+ entry = ptep_get_and_clear(pte);
+ set_pte(pte, pte_modify(entry, newprot));
+ }
+ address += PAGE_SIZE;
+ pte++;
+ } while (address && (address < end));
+}
+
+static inline void change_pmd_range(pgd_t * pgd, unsigned long address,
+ unsigned long size, pgprot_t newprot)
+{
+ pmd_t * pmd;
+ unsigned long end;
+
+ if (pgd_none(*pgd))
+ return;
+ if (pgd_bad(*pgd)) {
+ pgd_ERROR(*pgd);
+ pgd_clear(pgd);
+ return;
+ }
+ pmd = pmd_offset(pgd, address);
+ address &= ~PGDIR_MASK;
+ end = address + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ do {
+ change_pte_range(pmd, address, end - address, newprot);
+ address = (address + PMD_SIZE) & PMD_MASK;
+ pmd++;
+ } while (address && (address < end));
+}
+
+static void change_protection(unsigned long start, unsigned long end, pgprot_t newprot)
+{
+ pgd_t *dir;
+ unsigned long beg = start;
+
+ dir = pgd_offset(current->mm, start);
+ flush_cache_range(current->mm, beg, end);
+ if (start >= end)
+ BUG();
+ spin_lock(¤t->mm->page_table_lock);
+ do {
+ change_pmd_range(dir, start, end - start, newprot);
+ start = (start + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+ } while (start && (start < end));
+ spin_unlock(¤t->mm->page_table_lock);
+ flush_tlb_range(current->mm, beg, end);
+ return;
+}
+
+static inline int mprotect_fixup_all(struct vm_area_struct * vma, struct vm_area_struct ** pprev,
+ int newflags, pgprot_t prot)
+{
+ struct vm_area_struct * prev = *pprev;
+ struct mm_struct * mm = vma->vm_mm;
+
+ if (prev && prev->vm_end == vma->vm_start && can_vma_merge(prev, newflags) &&
+ !vma->vm_file && !(vma->vm_flags & VM_SHARED)) {
+ spin_lock(&mm->page_table_lock);
+ prev->vm_end = vma->vm_end;
+ __vma_unlink(mm, vma, prev);
+ spin_unlock(&mm->page_table_lock);
+
+ kmem_cache_free(vm_area_cachep, vma);
+ mm->map_count--;
+
+ return 0;
+ }
+
+ spin_lock(&mm->page_table_lock);
+ vma->vm_flags = newflags;
+ vma->vm_page_prot = prot;
+ spin_unlock(&mm->page_table_lock);
+
+ *pprev = vma;
+
+ return 0;
+}
+
+static inline int mprotect_fixup_start(struct vm_area_struct * vma, struct vm_area_struct ** pprev,
+ unsigned long end,
+ int newflags, pgprot_t prot)
+{
+ struct vm_area_struct * n, * prev = *pprev;
+
+ *pprev = vma;
+
+ if (prev && prev->vm_end == vma->vm_start && can_vma_merge(prev, newflags) &&
+ !vma->vm_file && !(vma->vm_flags & VM_SHARED)) {
+ spin_lock(&vma->vm_mm->page_table_lock);
+ prev->vm_end = end;
+ vma->vm_start = end;
+ spin_unlock(&vma->vm_mm->page_table_lock);
+
+ return 0;
+ }
+ n = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+ if (!n)
+ return -ENOMEM;
+ *n = *vma;
+ n->vm_end = end;
+ n->vm_flags = newflags;
+ n->vm_raend = 0;
+ n->vm_page_prot = prot;
+ if (n->vm_file)
+ get_file(n->vm_file);
+ if (n->vm_ops && n->vm_ops->open)
+ n->vm_ops->open(n);
+ vma->vm_pgoff += (end - vma->vm_start) >> PAGE_SHIFT;
+ lock_vma_mappings(vma);
+ spin_lock(&vma->vm_mm->page_table_lock);
+ vma->vm_start = end;
+ __insert_vm_struct(current->mm, n);
+ spin_unlock(&vma->vm_mm->page_table_lock);
+ unlock_vma_mappings(vma);
+
+ return 0;
+}
+
+static inline int mprotect_fixup_end(struct vm_area_struct * vma, struct vm_area_struct ** pprev,
+ unsigned long start,
+ int newflags, pgprot_t prot)
+{
+ struct vm_area_struct * n;
+
+ n = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
+ if (!n)
+ return -ENOMEM;
+ *n = *vma;
+ n->vm_start = start;
+ n->vm_pgoff += (n->vm_start - vma->vm_start) >> PAGE_SHIFT;
+ n->vm_flags = newflags;
+ n->vm_raend = 0;
+ n->vm_page_prot = prot;
+ if (n->vm_file)
+ get_file(n->vm_file);
+ if (n->vm_ops && n->vm_ops->open)
+ n->vm_ops->open(n);
+ lock_vma_mappings(vma);
+ spin_lock(&vma->vm_mm->page_table_lock);
+ vma->vm_end = start;
+ __insert_vm_struct(current->mm, n);
+ spin_unlock(&vma->vm_mm->page_table_lock);
+ unlock_vma_mappings(vma);
+
+ *pprev = n;
+
+ return 0;
+}
+
+static inline int mprotect_fixup_middle(struct vm_area_struct * vma, struct vm_area_struct ** pprev,
+ unsigned long start, unsigned long end,
+ int newflags, pgprot_t prot)
+{
+ struct vm_area_struct * left, * right;
+
+ left = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+ if (!left)
+ return -ENOMEM;
+ right = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+ if (!right) {
+ kmem_cache_free(vm_area_cachep, left);
+ return -ENOMEM;
+ }
+ *left = *vma;
+ *right = *vma;
+ left->vm_end = start;
+ right->vm_start = end;
+ right->vm_pgoff += (right->vm_start - left->vm_start) >> PAGE_SHIFT;
+ left->vm_raend = 0;
+ right->vm_raend = 0;
+ if (vma->vm_file)
+ atomic_add(2,&vma->vm_file->f_count);
+ if (vma->vm_ops && vma->vm_ops->open) {
+ vma->vm_ops->open(left);
+ vma->vm_ops->open(right);
+ }
+ vma->vm_pgoff += (start - vma->vm_start) >> PAGE_SHIFT;
+ vma->vm_raend = 0;
+ vma->vm_page_prot = prot;
+ lock_vma_mappings(vma);
+ spin_lock(&vma->vm_mm->page_table_lock);
+ vma->vm_start = start;
+ vma->vm_end = end;
+ vma->vm_flags = newflags;
+ __insert_vm_struct(current->mm, left);
+ __insert_vm_struct(current->mm, right);
+ spin_unlock(&vma->vm_mm->page_table_lock);
+ unlock_vma_mappings(vma);
+
+ *pprev = right;
+
+ return 0;
+}
+
+static int mprotect_fixup(struct vm_area_struct * vma, struct vm_area_struct ** pprev,
+ unsigned long start, unsigned long end, unsigned int newflags)
+{
+ pgprot_t newprot;
+ int error;
+
+ if (newflags == vma->vm_flags) {
+ *pprev = vma;
+ return 0;
+ }
+ newprot = protection_map[newflags & 0xf];
+ if (start == vma->vm_start) {
+ if (end == vma->vm_end)
+ error = mprotect_fixup_all(vma, pprev, newflags, newprot);
+ else
+ error = mprotect_fixup_start(vma, pprev, end, newflags, newprot);
+ } else if (end == vma->vm_end)
+ error = mprotect_fixup_end(vma, pprev, start, newflags, newprot);
+ else
+ error = mprotect_fixup_middle(vma, pprev, start, end, newflags, newprot);
+
+ if (error)
+ return error;
+
+ change_protection(start, end, newprot);
+ return 0;
+}
+
+asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot)
+{
+ unsigned long nstart, end, tmp;
+ struct vm_area_struct * vma, * next, * prev;
+ int error = -EINVAL;
+
+ if (start & ~PAGE_MASK)
+ return -EINVAL;
+ len = PAGE_ALIGN(len);
+ end = start + len;
+ if (end < start)
+ return -EINVAL;
+ if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
+ return -EINVAL;
+ if (end == start)
+ return 0;
+
+ down_write(¤t->mm->mmap_sem);
+
+ vma = find_vma_prev(current->mm, start, &prev);
+ error = -ENOMEM;
+ if (!vma || vma->vm_start > start)
+ goto out;
+
+#if defined(CONFIG_XENO_PRIV)
+ /* mprotect() unsupported for I/O mappings in Xenolinux. */
+ error = -EINVAL;
+ if (vma->vm_flags & VM_IO)
+ goto out;
+#endif
+
+ for (nstart = start ; ; ) {
+ unsigned int newflags;
+ int last = 0;
+
+ /* Here we know that vma->vm_start <= nstart < vma->vm_end. */
+
+ newflags = prot | (vma->vm_flags & ~(PROT_READ | PROT_WRITE | PROT_EXEC));
+ if ((newflags & ~(newflags >> 4)) & 0xf) {
+ error = -EACCES;
+ goto out;
+ }
+
+ if (vma->vm_end > end) {
+ error = mprotect_fixup(vma, &prev, nstart, end, newflags);
+ goto out;
+ }
+ if (vma->vm_end == end)
+ last = 1;
+
+ tmp = vma->vm_end;
+ next = vma->vm_next;
+ error = mprotect_fixup(vma, &prev, nstart, tmp, newflags);
+ if (error)
+ goto out;
+ if (last)
+ break;
+ nstart = tmp;
+ vma = next;
+ if (!vma || vma->vm_start != nstart) {
+ error = -ENOMEM;
+ goto out;
+ }
+ }
+ if (next && prev->vm_end == next->vm_start && can_vma_merge(next, prev->vm_flags) &&
+ !prev->vm_file && !(prev->vm_flags & VM_SHARED)) {
+ spin_lock(&prev->vm_mm->page_table_lock);
+ prev->vm_end = next->vm_end;
+ __vma_unlink(prev->vm_mm, next, prev);
+ spin_unlock(&prev->vm_mm->page_table_lock);
+
+ kmem_cache_free(vm_area_cachep, next);
+ prev->vm_mm->map_count--;
+ }
+out:
+ up_write(¤t->mm->mmap_sem);
+ return error;
+}
!vm_enough_memory((new_len - old_len) >> PAGE_SHIFT))
goto out;
+#if defined(CONFIG_XENO_PRIV)
+ /* mremap() unsupported for I/O mappings in Xenolinux. */
+ ret = -EINVAL;
+ if (vma->vm_flags & VM_IO)
+ goto out;
+#endif
+
/* old_len exactly to the end of the area..
* And we're not relocating the area.
*/
--- /dev/null
+/*
+ * linux/mm/vmalloc.c
+ *
+ * Copyright (C) 1993 Linus Torvalds
+ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+ * SMP-safe vmalloc/vfree/ioremap, Tigran Aivazian <tigran@veritas.com>, May 2000
+ */
+
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/spinlock.h>
+#include <linux/highmem.h>
+#include <linux/smp_lock.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+
+rwlock_t vmlist_lock = RW_LOCK_UNLOCKED;
+struct vm_struct * vmlist;
+
+static inline void free_area_pte(pmd_t * pmd, unsigned long address, unsigned long size)
+{
+ pte_t * pte;
+ unsigned long end;
+
+ if (pmd_none(*pmd))
+ return;
+ if (pmd_bad(*pmd)) {
+ pmd_ERROR(*pmd);
+ pmd_clear(pmd);
+ return;
+ }
+ pte = pte_offset(pmd, address);
+ address &= ~PMD_MASK;
+ end = address + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ do {
+ pte_t page;
+ page = ptep_get_and_clear(pte);
+ address += PAGE_SIZE;
+ pte++;
+ if (pte_none(page))
+ continue;
+ if (pte_present(page)) {
+ struct page *ptpage = pte_page(page);
+ if (VALID_PAGE(ptpage) && (!PageReserved(ptpage)))
+ __free_page(ptpage);
+ continue;
+ }
+ printk(KERN_CRIT "Whee.. Swapped out page in kernel page table\n");
+ } while (address < end);
+}
+
+static inline void free_area_pmd(pgd_t * dir, unsigned long address, unsigned long size)
+{
+ pmd_t * pmd;
+ unsigned long end;
+
+ if (pgd_none(*dir))
+ return;
+ if (pgd_bad(*dir)) {
+ pgd_ERROR(*dir);
+ pgd_clear(dir);
+ return;
+ }
+ pmd = pmd_offset(dir, address);
+ address &= ~PGDIR_MASK;
+ end = address + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ do {
+ free_area_pte(pmd, address, end - address);
+ address = (address + PMD_SIZE) & PMD_MASK;
+ pmd++;
+ } while (address < end);
+}
+
+void vmfree_area_pages(unsigned long address, unsigned long size)
+{
+ pgd_t * dir;
+ unsigned long end = address + size;
+
+ dir = pgd_offset_k(address);
+ flush_cache_all();
+ do {
+ free_area_pmd(dir, address, end - address);
+ address = (address + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+ } while (address && (address < end));
+ flush_tlb_all();
+}
+
+static inline int alloc_area_pte (pte_t * pte, unsigned long address,
+ unsigned long size, int gfp_mask, pgprot_t prot)
+{
+ unsigned long end;
+
+ address &= ~PMD_MASK;
+ end = address + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ do {
+ struct page * page;
+ spin_unlock(&init_mm.page_table_lock);
+ page = alloc_page(gfp_mask);
+ spin_lock(&init_mm.page_table_lock);
+ if (!pte_none(*pte))
+ printk(KERN_ERR "alloc_area_pte: page already exists\n");
+ if (!page)
+ return -ENOMEM;
+ set_pte(pte, mk_pte(page, prot));
+ address += PAGE_SIZE;
+ pte++;
+ } while (address < end);
+ return 0;
+}
+
+static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, int gfp_mask, pgprot_t prot)
+{
+ unsigned long end;
+
+ address &= ~PGDIR_MASK;
+ end = address + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ do {
+ pte_t * pte = pte_alloc(&init_mm, pmd, address);
+ if (!pte)
+ return -ENOMEM;
+ if (alloc_area_pte(pte, address, end - address, gfp_mask, prot))
+ return -ENOMEM;
+ address = (address + PMD_SIZE) & PMD_MASK;
+ pmd++;
+ } while (address < end);
+ return 0;
+}
+
+inline int vmalloc_area_pages (unsigned long address, unsigned long size,
+ int gfp_mask, pgprot_t prot)
+{
+ pgd_t * dir;
+ unsigned long end = address + size;
+ int ret;
+
+ dir = pgd_offset_k(address);
+ spin_lock(&init_mm.page_table_lock);
+ do {
+ pmd_t *pmd;
+
+ pmd = pmd_alloc(&init_mm, dir, address);
+ ret = -ENOMEM;
+ if (!pmd)
+ break;
+
+ ret = -ENOMEM;
+ if (alloc_area_pmd(pmd, address, end - address, gfp_mask, prot))
+ break;
+
+ address = (address + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+
+ ret = 0;
+ } while (address && (address < end));
+ spin_unlock(&init_mm.page_table_lock);
+ flush_cache_all();
+ return ret;
+}
+
+struct vm_struct * get_vm_area(unsigned long size, unsigned long flags)
+{
+ unsigned long addr, next;
+ struct vm_struct **p, *tmp, *area;
+
+ area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
+ if (!area)
+ return NULL;
+
+ size += PAGE_SIZE;
+ if (!size) {
+ kfree (area);
+ return NULL;
+ }
+
+ addr = VMALLOC_START;
+ write_lock(&vmlist_lock);
+ for (p = &vmlist; (tmp = *p) ; p = &tmp->next) {
+ if ((size + addr) < addr)
+ goto out;
+ if (size + addr <= (unsigned long) tmp->addr)
+ break;
+ next = tmp->size + (unsigned long) tmp->addr;
+ if (next > addr)
+ addr = next;
+ if (addr > VMALLOC_END-size)
+ goto out;
+ }
+ area->flags = flags;
+ area->addr = (void *)addr;
+ area->size = size;
+ area->next = *p;
+ *p = area;
+ write_unlock(&vmlist_lock);
+ return area;
+
+out:
+ write_unlock(&vmlist_lock);
+ kfree(area);
+ return NULL;
+}
+
+void vfree(void * addr)
+{
+ struct vm_struct **p, *tmp;
+
+ if (!addr)
+ return;
+ if ((PAGE_SIZE-1) & (unsigned long) addr) {
+ printk(KERN_ERR "Trying to vfree() bad address (%p)\n", addr);
+ return;
+ }
+ write_lock(&vmlist_lock);
+ for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
+ if (tmp->addr == addr) {
+ *p = tmp->next;
+#ifdef CONFIG_XENO_PRIV
+ if (tmp->flags & VM_IOREMAP)
+ zap_page_range(&init_mm, VMALLOC_VMADDR(tmp->addr), tmp->size);
+ else
+#endif
+ vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size);
+ write_unlock(&vmlist_lock);
+ kfree(tmp);
+ return;
+ }
+ }
+ write_unlock(&vmlist_lock);
+ printk(KERN_ERR "Trying to vfree() nonexistent vm area (%p)\n", addr);
+}
+
+void * __vmalloc (unsigned long size, int gfp_mask, pgprot_t prot)
+{
+ void * addr;
+ struct vm_struct *area;
+
+ size = PAGE_ALIGN(size);
+ if (!size || (size >> PAGE_SHIFT) > num_physpages)
+ return NULL;
+ area = get_vm_area(size, VM_ALLOC);
+ if (!area)
+ return NULL;
+ addr = area->addr;
+ if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size, gfp_mask, prot)) {
+ vfree(addr);
+ return NULL;
+ }
+ return addr;
+}
+
+long vread(char *buf, char *addr, unsigned long count)
+{
+ struct vm_struct *tmp;
+ char *vaddr, *buf_start = buf;
+ unsigned long n;
+
+ /* Don't allow overflow */
+ if ((unsigned long) addr + count < count)
+ count = -(unsigned long) addr;
+
+ read_lock(&vmlist_lock);
+ for (tmp = vmlist; tmp; tmp = tmp->next) {
+ vaddr = (char *) tmp->addr;
+ if (addr >= vaddr + tmp->size - PAGE_SIZE)
+ continue;
+ while (addr < vaddr) {
+ if (count == 0)
+ goto finished;
+ *buf = '\0';
+ buf++;
+ addr++;
+ count--;
+ }
+ n = vaddr + tmp->size - PAGE_SIZE - addr;
+ do {
+ if (count == 0)
+ goto finished;
+ *buf = *addr;
+ buf++;
+ addr++;
+ count--;
+ } while (--n > 0);
+ }
+finished:
+ read_unlock(&vmlist_lock);
+ return buf - buf_start;
+}
+
+long vwrite(char *buf, char *addr, unsigned long count)
+{
+ struct vm_struct *tmp;
+ char *vaddr, *buf_start = buf;
+ unsigned long n;
+
+ /* Don't allow overflow */
+ if ((unsigned long) addr + count < count)
+ count = -(unsigned long) addr;
+
+ read_lock(&vmlist_lock);
+ for (tmp = vmlist; tmp; tmp = tmp->next) {
+ vaddr = (char *) tmp->addr;
+ if (addr >= vaddr + tmp->size - PAGE_SIZE)
+ continue;
+ while (addr < vaddr) {
+ if (count == 0)
+ goto finished;
+ buf++;
+ addr++;
+ count--;
+ }
+ n = vaddr + tmp->size - PAGE_SIZE - addr;
+ do {
+ if (count == 0)
+ goto finished;
+ *addr = *buf;
+ buf++;
+ addr++;
+ count--;
+ } while (--n > 0);
+ }
+finished:
+ read_unlock(&vmlist_lock);
+ return buf - buf_start;
+}